diff options
85 files changed, 1267 insertions, 18406 deletions
diff --git a/bin/date/date.1 b/bin/date/date.1 index 62d28a7df0a0..b86a660a924d 100644 --- a/bin/date/date.1 +++ b/bin/date/date.1 @@ -29,7 +29,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd September 10, 2024 +.Dd September 1, 2025 .Dt DATE 1 .Os .Sh NAME @@ -129,7 +129,7 @@ format. Parsing is done using .Xr strptime 3 . .It Fl I Ns Op Ar FMT -Use +Use extended .St -iso8601 output format. .Ar FMT @@ -154,9 +154,9 @@ is .Cm seconds , or .Cm ns Pc , -the +the extended .St -iso8601 -format includes the timezone. +format includes the timezone offset. .It Fl j Do not try to set the date. This allows you to use the diff --git a/bin/sh/Makefile b/bin/sh/Makefile index 087dbf40c3bd..916bb88b57fa 100644 --- a/bin/sh/Makefile +++ b/bin/sh/Makefile @@ -74,6 +74,6 @@ beforeinstallconfig: LINKMODE=${CONFMODE} afterinstallconfig: - ${INSTALL_LINK} ${TAG_ARGS} ${DESTDIR}/root/.profile ${DESTDIR}/.profile + ${INSTALL_LINK} ${TAG_ARGS:D${TAG_ARGS},config} ${DESTDIR}/root/.profile ${DESTDIR}/.profile .include <bsd.prog.mk> diff --git a/contrib/jemalloc/INSTALL.md b/contrib/jemalloc/INSTALL.md index 9701364041c8..90da718d2b6a 100644 --- a/contrib/jemalloc/INSTALL.md +++ b/contrib/jemalloc/INSTALL.md @@ -1,4 +1,3 @@ -<<<<<<< HEAD Building and installing a packaged release of jemalloc can be as simple as typing the following while in the root directory of the source tree: @@ -423,427 +422,3 @@ can be used to view the html manual. The roff manual page can be formatted prior to installation via the following command: nroff -man -t doc/jemalloc.3 -||||||| dec341af7695 -======= -Building and installing a packaged release of jemalloc can be as simple as -typing the following while in the root directory of the source tree: - - ./configure - make - make install - -If building from unpackaged developer sources, the simplest command sequence -that might work is: - - ./autogen.sh - make dist - make - make install - -Note that documentation is not built by the default target because doing so -would create a dependency on xsltproc in packaged releases, hence the -requirement to either run 'make dist' or avoid installing docs via the various -install_* targets documented below. - - -## Advanced configuration - -The 'configure' script supports numerous options that allow control of which -functionality is enabled, where jemalloc is installed, etc. Optionally, pass -any of the following arguments (not a definitive list) to 'configure': - -* `--help` - - Print a definitive list of options. - -* `--prefix=<install-root-dir>` - - Set the base directory in which to install. For example: - - ./configure --prefix=/usr/local - - will cause files to be installed into /usr/local/include, /usr/local/lib, - and /usr/local/man. - -* `--with-version=(<major>.<minor>.<bugfix>-<nrev>-g<gid>|VERSION)` - - The VERSION file is mandatory for successful configuration, and the - following steps are taken to assure its presence: - 1) If --with-version=<major>.<minor>.<bugfix>-<nrev>-g<gid> is specified, - generate VERSION using the specified value. - 2) If --with-version is not specified in either form and the source - directory is inside a git repository, try to generate VERSION via 'git - describe' invocations that pattern-match release tags. - 3) If VERSION is missing, generate it with a bogus version: - 0.0.0-0-g0000000000000000000000000000000000000000 - - Note that --with-version=VERSION bypasses (1) and (2), which simplifies - VERSION configuration when embedding a jemalloc release into another - project's git repository. - -* `--with-rpath=<colon-separated-rpath>` - - Embed one or more library paths, so that libjemalloc can find the libraries - it is linked to. This works only on ELF-based systems. - -* `--with-mangling=<map>` - - Mangle public symbols specified in <map> which is a comma-separated list of - name:mangled pairs. - - For example, to use ld's --wrap option as an alternative method for - overriding libc's malloc implementation, specify something like: - - --with-mangling=malloc:__wrap_malloc,free:__wrap_free[...] - - Note that mangling happens prior to application of the prefix specified by - --with-jemalloc-prefix, and mangled symbols are then ignored when applying - the prefix. - -* `--with-jemalloc-prefix=<prefix>` - - Prefix all public APIs with <prefix>. For example, if <prefix> is - "prefix_", API changes like the following occur: - - malloc() --> prefix_malloc() - malloc_conf --> prefix_malloc_conf - /etc/malloc.conf --> /etc/prefix_malloc.conf - MALLOC_CONF --> PREFIX_MALLOC_CONF - - This makes it possible to use jemalloc at the same time as the system - allocator, or even to use multiple copies of jemalloc simultaneously. - - By default, the prefix is "", except on OS X, where it is "je_". On OS X, - jemalloc overlays the default malloc zone, but makes no attempt to actually - replace the "malloc", "calloc", etc. symbols. - -* `--without-export` - - Don't export public APIs. This can be useful when building jemalloc as a - static library, or to avoid exporting public APIs when using the zone - allocator on OSX. - -* `--with-private-namespace=<prefix>` - - Prefix all library-private APIs with <prefix>je_. For shared libraries, - symbol visibility mechanisms prevent these symbols from being exported, but - for static libraries, naming collisions are a real possibility. By - default, <prefix> is empty, which results in a symbol prefix of je_ . - -* `--with-install-suffix=<suffix>` - - Append <suffix> to the base name of all installed files, such that multiple - versions of jemalloc can coexist in the same installation directory. For - example, libjemalloc.so.0 becomes libjemalloc<suffix>.so.0. - -* `--with-malloc-conf=<malloc_conf>` - - Embed `<malloc_conf>` as a run-time options string that is processed prior to - the malloc_conf global variable, the /etc/malloc.conf symlink, and the - MALLOC_CONF environment variable. For example, to change the default decay - time to 30 seconds: - - --with-malloc-conf=decay_ms:30000 - -* `--enable-debug` - - Enable assertions and validation code. This incurs a substantial - performance hit, but is very useful during application development. - -* `--disable-stats` - - Disable statistics gathering functionality. See the "opt.stats_print" - option documentation for usage details. - -* `--enable-prof` - - Enable heap profiling and leak detection functionality. See the "opt.prof" - option documentation for usage details. When enabled, there are several - approaches to backtracing, and the configure script chooses the first one - in the following list that appears to function correctly: - - + libunwind (requires --enable-prof-libunwind) - + libgcc (unless --disable-prof-libgcc) - + gcc intrinsics (unless --disable-prof-gcc) - -* `--enable-prof-libunwind` - - Use the libunwind library (http://www.nongnu.org/libunwind/) for stack - backtracing. - -* `--disable-prof-libgcc` - - Disable the use of libgcc's backtracing functionality. - -* `--disable-prof-gcc` - - Disable the use of gcc intrinsics for backtracing. - -* `--with-static-libunwind=<libunwind.a>` - - Statically link against the specified libunwind.a rather than dynamically - linking with -lunwind. - -* `--disable-fill` - - Disable support for junk/zero filling of memory. See the "opt.junk" and - "opt.zero" option documentation for usage details. - -* `--disable-zone-allocator` - - Disable zone allocator for Darwin. This means jemalloc won't be hooked as - the default allocator on OSX/iOS. - -* `--enable-utrace` - - Enable utrace(2)-based allocation tracing. This feature is not broadly - portable (FreeBSD has it, but Linux and OS X do not). - -* `--enable-xmalloc` - - Enable support for optional immediate termination due to out-of-memory - errors, as is commonly implemented by "xmalloc" wrapper function for malloc. - See the "opt.xmalloc" option documentation for usage details. - -* `--enable-lazy-lock` - - Enable code that wraps pthread_create() to detect when an application - switches from single-threaded to multi-threaded mode, so that it can avoid - mutex locking/unlocking operations while in single-threaded mode. In - practice, this feature usually has little impact on performance unless - thread-specific caching is disabled. - -* `--disable-cache-oblivious` - - Disable cache-oblivious large allocation alignment for large allocation - requests with no alignment constraints. If this feature is disabled, all - large allocations are page-aligned as an implementation artifact, which can - severely harm CPU cache utilization. However, the cache-oblivious layout - comes at the cost of one extra page per large allocation, which in the - most extreme case increases physical memory usage for the 16 KiB size class - to 20 KiB. - -* `--disable-syscall` - - Disable use of syscall(2) rather than {open,read,write,close}(2). This is - intended as a workaround for systems that place security limitations on - syscall(2). - -* `--disable-cxx` - - Disable C++ integration. This will cause new and delete operator - implementations to be omitted. - -* `--with-xslroot=<path>` - - Specify where to find DocBook XSL stylesheets when building the - documentation. - -* `--with-lg-page=<lg-page>` - - Specify the base 2 log of the allocator page size, which must in turn be at - least as large as the system page size. By default the configure script - determines the host's page size and sets the allocator page size equal to - the system page size, so this option need not be specified unless the - system page size may change between configuration and execution, e.g. when - cross compiling. - -* `--with-lg-hugepage=<lg-hugepage>` - - Specify the base 2 log of the system huge page size. This option is useful - when cross compiling, or when overriding the default for systems that do - not explicitly support huge pages. - -* `--with-lg-quantum=<lg-quantum>` - - Specify the base 2 log of the minimum allocation alignment. jemalloc needs - to know the minimum alignment that meets the following C standard - requirement (quoted from the April 12, 2011 draft of the C11 standard): - - > The pointer returned if the allocation succeeds is suitably aligned so - that it may be assigned to a pointer to any type of object with a - fundamental alignment requirement and then used to access such an object - or an array of such objects in the space allocated [...] - - This setting is architecture-specific, and although jemalloc includes known - safe values for the most commonly used modern architectures, there is a - wrinkle related to GNU libc (glibc) that may impact your choice of - <lg-quantum>. On most modern architectures, this mandates 16-byte - alignment (<lg-quantum>=4), but the glibc developers chose not to meet this - requirement for performance reasons. An old discussion can be found at - <https://sourceware.org/bugzilla/show_bug.cgi?id=206> . Unlike glibc, - jemalloc does follow the C standard by default (caveat: jemalloc - technically cheats for size classes smaller than the quantum), but the fact - that Linux systems already work around this allocator noncompliance means - that it is generally safe in practice to let jemalloc's minimum alignment - follow glibc's lead. If you specify `--with-lg-quantum=3` during - configuration, jemalloc will provide additional size classes that are not - 16-byte-aligned (24, 40, and 56). - -* `--with-lg-vaddr=<lg-vaddr>` - - Specify the number of significant virtual address bits. By default, the - configure script attempts to detect virtual address size on those platforms - where it knows how, and picks a default otherwise. This option may be - useful when cross-compiling. - -* `--disable-initial-exec-tls` - - Disable the initial-exec TLS model for jemalloc's internal thread-local - storage (on those platforms that support explicit settings). This can allow - jemalloc to be dynamically loaded after program startup (e.g. using dlopen). - Note that in this case, there will be two malloc implementations operating - in the same process, which will almost certainly result in confusing runtime - crashes if pointers leak from one implementation to the other. - -* `--disable-libdl` - - Disable the usage of libdl, namely dlsym(3) which is required by the lazy - lock option. This can allow building static binaries. - -The following environment variables (not a definitive list) impact configure's -behavior: - -* `CFLAGS="?"` -* `CXXFLAGS="?"` - - Pass these flags to the C/C++ compiler. Any flags set by the configure - script are prepended, which means explicitly set flags generally take - precedence. Take care when specifying flags such as -Werror, because - configure tests may be affected in undesirable ways. - -* `EXTRA_CFLAGS="?"` -* `EXTRA_CXXFLAGS="?"` - - Append these flags to CFLAGS/CXXFLAGS, without passing them to the - compiler(s) during configuration. This makes it possible to add flags such - as -Werror, while allowing the configure script to determine what other - flags are appropriate for the specified configuration. - -* `CPPFLAGS="?"` - - Pass these flags to the C preprocessor. Note that CFLAGS is not passed to - 'cpp' when 'configure' is looking for include files, so you must use - CPPFLAGS instead if you need to help 'configure' find header files. - -* `LD_LIBRARY_PATH="?"` - - 'ld' uses this colon-separated list to find libraries. - -* `LDFLAGS="?"` - - Pass these flags when linking. - -* `PATH="?"` - - 'configure' uses this to find programs. - -In some cases it may be necessary to work around configuration results that do -not match reality. For example, Linux 4.5 added support for the MADV_FREE flag -to madvise(2), which can cause problems if building on a host with MADV_FREE -support and deploying to a target without. To work around this, use a cache -file to override the relevant configuration variable defined in configure.ac, -e.g.: - - echo "je_cv_madv_free=no" > config.cache && ./configure -C - - -## Advanced compilation - -To build only parts of jemalloc, use the following targets: - - build_lib_shared - build_lib_static - build_lib - build_doc_html - build_doc_man - build_doc - -To install only parts of jemalloc, use the following targets: - - install_bin - install_include - install_lib_shared - install_lib_static - install_lib_pc - install_lib - install_doc_html - install_doc_man - install_doc - -To clean up build results to varying degrees, use the following make targets: - - clean - distclean - relclean - - -## Advanced installation - -Optionally, define make variables when invoking make, including (not -exclusively): - -* `INCLUDEDIR="?"` - - Use this as the installation prefix for header files. - -* `LIBDIR="?"` - - Use this as the installation prefix for libraries. - -* `MANDIR="?"` - - Use this as the installation prefix for man pages. - -* `DESTDIR="?"` - - Prepend DESTDIR to INCLUDEDIR, LIBDIR, DATADIR, and MANDIR. This is useful - when installing to a different path than was specified via --prefix. - -* `CC="?"` - - Use this to invoke the C compiler. - -* `CFLAGS="?"` - - Pass these flags to the compiler. - -* `CPPFLAGS="?"` - - Pass these flags to the C preprocessor. - -* `LDFLAGS="?"` - - Pass these flags when linking. - -* `PATH="?"` - - Use this to search for programs used during configuration and building. - - -## Development - -If you intend to make non-trivial changes to jemalloc, use the 'autogen.sh' -script rather than 'configure'. This re-generates 'configure', enables -configuration dependency rules, and enables re-generation of automatically -generated source files. - -The build system supports using an object directory separate from the source -tree. For example, you can create an 'obj' directory, and from within that -directory, issue configuration and build commands: - - autoconf - mkdir obj - cd obj - ../configure --enable-autogen - make - - -## Documentation - -The manual page is generated in both html and roff formats. Any web browser -can be used to view the html manual. The roff manual page can be formatted -prior to installation via the following command: - - nroff -man -t doc/jemalloc.3 ->>>>>>> main diff --git a/contrib/jemalloc/Makefile.in b/contrib/jemalloc/Makefile.in index 121297702bcc..1193cd859c49 100644 --- a/contrib/jemalloc/Makefile.in +++ b/contrib/jemalloc/Makefile.in @@ -1,4 +1,3 @@ -<<<<<<< HEAD # Clear out all vpaths, then set just one (default vpath) for the main build # directory. vpath @@ -761,629 +760,3 @@ $(objroot)config.stamp : $(cfgoutputs_in) $(cfghdrs_in) $(srcroot)configure $(cfgoutputs_out) $(cfghdrs_out) : $(objroot)config.stamp @true endif -||||||| dec341af7695 -======= -# Clear out all vpaths, then set just one (default vpath) for the main build -# directory. -vpath -vpath % . - -# Clear the default suffixes, so that built-in rules are not used. -.SUFFIXES : - -SHELL := /bin/sh - -CC := @CC@ -CXX := @CXX@ - -# Configuration parameters. -DESTDIR = -BINDIR := $(DESTDIR)@BINDIR@ -INCLUDEDIR := $(DESTDIR)@INCLUDEDIR@ -LIBDIR := $(DESTDIR)@LIBDIR@ -DATADIR := $(DESTDIR)@DATADIR@ -MANDIR := $(DESTDIR)@MANDIR@ -srcroot := @srcroot@ -objroot := @objroot@ -abs_srcroot := @abs_srcroot@ -abs_objroot := @abs_objroot@ - -# Build parameters. -CPPFLAGS := @CPPFLAGS@ -I$(objroot)include -I$(srcroot)include -CONFIGURE_CFLAGS := @CONFIGURE_CFLAGS@ -SPECIFIED_CFLAGS := @SPECIFIED_CFLAGS@ -EXTRA_CFLAGS := @EXTRA_CFLAGS@ -CFLAGS := $(strip $(CONFIGURE_CFLAGS) $(SPECIFIED_CFLAGS) $(EXTRA_CFLAGS)) -CONFIGURE_CXXFLAGS := @CONFIGURE_CXXFLAGS@ -SPECIFIED_CXXFLAGS := @SPECIFIED_CXXFLAGS@ -EXTRA_CXXFLAGS := @EXTRA_CXXFLAGS@ -CXXFLAGS := $(strip $(CONFIGURE_CXXFLAGS) $(SPECIFIED_CXXFLAGS) $(EXTRA_CXXFLAGS)) -LDFLAGS := @LDFLAGS@ -EXTRA_LDFLAGS := @EXTRA_LDFLAGS@ -LIBS := @LIBS@ -RPATH_EXTRA := @RPATH_EXTRA@ -SO := @so@ -IMPORTLIB := @importlib@ -O := @o@ -A := @a@ -EXE := @exe@ -LIBPREFIX := @libprefix@ -REV := @rev@ -install_suffix := @install_suffix@ -ABI := @abi@ -XSLTPROC := @XSLTPROC@ -XSLROOT := @XSLROOT@ -AUTOCONF := @AUTOCONF@ -_RPATH = @RPATH@ -RPATH = $(if $(1),$(call _RPATH,$(1))) -cfghdrs_in := $(addprefix $(srcroot),@cfghdrs_in@) -cfghdrs_out := @cfghdrs_out@ -cfgoutputs_in := $(addprefix $(srcroot),@cfgoutputs_in@) -cfgoutputs_out := @cfgoutputs_out@ -enable_autogen := @enable_autogen@ -enable_doc := @enable_doc@ -enable_shared := @enable_shared@ -enable_static := @enable_static@ -enable_prof := @enable_prof@ -enable_zone_allocator := @enable_zone_allocator@ -enable_experimental_smallocx := @enable_experimental_smallocx@ -MALLOC_CONF := @JEMALLOC_CPREFIX@MALLOC_CONF -link_whole_archive := @link_whole_archive@ -DSO_LDFLAGS = @DSO_LDFLAGS@ -SOREV = @SOREV@ -PIC_CFLAGS = @PIC_CFLAGS@ -CTARGET = @CTARGET@ -LDTARGET = @LDTARGET@ -TEST_LD_MODE = @TEST_LD_MODE@ -MKLIB = @MKLIB@ -AR = @AR@ -ARFLAGS = @ARFLAGS@ -DUMP_SYMS = @DUMP_SYMS@ -AWK := @AWK@ -CC_MM = @CC_MM@ -LM := @LM@ -INSTALL = @INSTALL@ - -ifeq (macho, $(ABI)) -TEST_LIBRARY_PATH := DYLD_FALLBACK_LIBRARY_PATH="$(objroot)lib" -else -ifeq (pecoff, $(ABI)) -TEST_LIBRARY_PATH := PATH="$(PATH):$(objroot)lib" -else -TEST_LIBRARY_PATH := -endif -endif - -LIBJEMALLOC := $(LIBPREFIX)jemalloc$(install_suffix) - -# Lists of files. -BINS := $(objroot)bin/jemalloc-config $(objroot)bin/jemalloc.sh $(objroot)bin/jeprof -C_HDRS := $(objroot)include/jemalloc/jemalloc$(install_suffix).h -C_SRCS := $(srcroot)src/jemalloc.c \ - $(srcroot)src/arena.c \ - $(srcroot)src/background_thread.c \ - $(srcroot)src/base.c \ - $(srcroot)src/bin.c \ - $(srcroot)src/bitmap.c \ - $(srcroot)src/ckh.c \ - $(srcroot)src/ctl.c \ - $(srcroot)src/div.c \ - $(srcroot)src/extent.c \ - $(srcroot)src/extent_dss.c \ - $(srcroot)src/extent_mmap.c \ - $(srcroot)src/hash.c \ - $(srcroot)src/hook.c \ - $(srcroot)src/large.c \ - $(srcroot)src/log.c \ - $(srcroot)src/malloc_io.c \ - $(srcroot)src/mutex.c \ - $(srcroot)src/mutex_pool.c \ - $(srcroot)src/nstime.c \ - $(srcroot)src/pages.c \ - $(srcroot)src/prng.c \ - $(srcroot)src/prof.c \ - $(srcroot)src/rtree.c \ - $(srcroot)src/safety_check.c \ - $(srcroot)src/stats.c \ - $(srcroot)src/sc.c \ - $(srcroot)src/sz.c \ - $(srcroot)src/tcache.c \ - $(srcroot)src/test_hooks.c \ - $(srcroot)src/ticker.c \ - $(srcroot)src/tsd.c \ - $(srcroot)src/witness.c -ifeq ($(enable_zone_allocator), 1) -C_SRCS += $(srcroot)src/zone.c -endif -ifeq ($(IMPORTLIB),$(SO)) -STATIC_LIBS := $(objroot)lib/$(LIBJEMALLOC).$(A) -endif -ifdef PIC_CFLAGS -STATIC_LIBS += $(objroot)lib/$(LIBJEMALLOC)_pic.$(A) -else -STATIC_LIBS += $(objroot)lib/$(LIBJEMALLOC)_s.$(A) -endif -DSOS := $(objroot)lib/$(LIBJEMALLOC).$(SOREV) -ifneq ($(SOREV),$(SO)) -DSOS += $(objroot)lib/$(LIBJEMALLOC).$(SO) -endif -ifeq (1, $(link_whole_archive)) -LJEMALLOC := -Wl,--whole-archive -L$(objroot)lib -l$(LIBJEMALLOC) -Wl,--no-whole-archive -else -LJEMALLOC := $(objroot)lib/$(LIBJEMALLOC).$(IMPORTLIB) -endif -PC := $(objroot)jemalloc.pc -MAN3 := $(objroot)doc/jemalloc$(install_suffix).3 -DOCS_XML := $(objroot)doc/jemalloc$(install_suffix).xml -DOCS_HTML := $(DOCS_XML:$(objroot)%.xml=$(objroot)%.html) -DOCS_MAN3 := $(DOCS_XML:$(objroot)%.xml=$(objroot)%.3) -DOCS := $(DOCS_HTML) $(DOCS_MAN3) -C_TESTLIB_SRCS := $(srcroot)test/src/btalloc.c $(srcroot)test/src/btalloc_0.c \ - $(srcroot)test/src/btalloc_1.c $(srcroot)test/src/math.c \ - $(srcroot)test/src/mtx.c $(srcroot)test/src/mq.c \ - $(srcroot)test/src/SFMT.c $(srcroot)test/src/test.c \ - $(srcroot)test/src/thd.c $(srcroot)test/src/timer.c -ifeq (1, $(link_whole_archive)) -C_UTIL_INTEGRATION_SRCS := -C_UTIL_CPP_SRCS := -else -C_UTIL_INTEGRATION_SRCS := $(srcroot)src/nstime.c $(srcroot)src/malloc_io.c -C_UTIL_CPP_SRCS := $(srcroot)src/nstime.c $(srcroot)src/malloc_io.c -endif -TESTS_UNIT := \ - $(srcroot)test/unit/a0.c \ - $(srcroot)test/unit/arena_reset.c \ - $(srcroot)test/unit/atomic.c \ - $(srcroot)test/unit/background_thread.c \ - $(srcroot)test/unit/background_thread_enable.c \ - $(srcroot)test/unit/base.c \ - $(srcroot)test/unit/bitmap.c \ - $(srcroot)test/unit/bit_util.c \ - $(srcroot)test/unit/binshard.c \ - $(srcroot)test/unit/ckh.c \ - $(srcroot)test/unit/decay.c \ - $(srcroot)test/unit/div.c \ - $(srcroot)test/unit/emitter.c \ - $(srcroot)test/unit/extent_quantize.c \ - $(srcroot)test/unit/extent_util.c \ - $(srcroot)test/unit/fork.c \ - $(srcroot)test/unit/hash.c \ - $(srcroot)test/unit/hook.c \ - $(srcroot)test/unit/huge.c \ - $(srcroot)test/unit/junk.c \ - $(srcroot)test/unit/junk_alloc.c \ - $(srcroot)test/unit/junk_free.c \ - $(srcroot)test/unit/log.c \ - $(srcroot)test/unit/mallctl.c \ - $(srcroot)test/unit/malloc_io.c \ - $(srcroot)test/unit/math.c \ - $(srcroot)test/unit/mq.c \ - $(srcroot)test/unit/mtx.c \ - $(srcroot)test/unit/pack.c \ - $(srcroot)test/unit/pages.c \ - $(srcroot)test/unit/ph.c \ - $(srcroot)test/unit/prng.c \ - $(srcroot)test/unit/prof_accum.c \ - $(srcroot)test/unit/prof_active.c \ - $(srcroot)test/unit/prof_gdump.c \ - $(srcroot)test/unit/prof_idump.c \ - $(srcroot)test/unit/prof_log.c \ - $(srcroot)test/unit/prof_reset.c \ - $(srcroot)test/unit/prof_tctx.c \ - $(srcroot)test/unit/prof_thread_name.c \ - $(srcroot)test/unit/ql.c \ - $(srcroot)test/unit/qr.c \ - $(srcroot)test/unit/rb.c \ - $(srcroot)test/unit/retained.c \ - $(srcroot)test/unit/rtree.c \ - $(srcroot)test/unit/safety_check.c \ - $(srcroot)test/unit/seq.c \ - $(srcroot)test/unit/SFMT.c \ - $(srcroot)test/unit/sc.c \ - $(srcroot)test/unit/size_classes.c \ - $(srcroot)test/unit/slab.c \ - $(srcroot)test/unit/smoothstep.c \ - $(srcroot)test/unit/spin.c \ - $(srcroot)test/unit/stats.c \ - $(srcroot)test/unit/stats_print.c \ - $(srcroot)test/unit/test_hooks.c \ - $(srcroot)test/unit/ticker.c \ - $(srcroot)test/unit/nstime.c \ - $(srcroot)test/unit/tsd.c \ - $(srcroot)test/unit/witness.c \ - $(srcroot)test/unit/zero.c -ifeq (@enable_prof@, 1) -TESTS_UNIT += \ - $(srcroot)test/unit/arena_reset_prof.c -endif -TESTS_INTEGRATION := $(srcroot)test/integration/aligned_alloc.c \ - $(srcroot)test/integration/allocated.c \ - $(srcroot)test/integration/extent.c \ - $(srcroot)test/integration/malloc.c \ - $(srcroot)test/integration/mallocx.c \ - $(srcroot)test/integration/MALLOCX_ARENA.c \ - $(srcroot)test/integration/overflow.c \ - $(srcroot)test/integration/posix_memalign.c \ - $(srcroot)test/integration/rallocx.c \ - $(srcroot)test/integration/sdallocx.c \ - $(srcroot)test/integration/slab_sizes.c \ - $(srcroot)test/integration/thread_arena.c \ - $(srcroot)test/integration/thread_tcache_enabled.c \ - $(srcroot)test/integration/xallocx.c -ifeq (@enable_experimental_smallocx@, 1) -TESTS_INTEGRATION += \ - $(srcroot)test/integration/smallocx.c -endif -ifeq (@enable_cxx@, 1) -CPP_SRCS := $(srcroot)src/jemalloc_cpp.cpp -TESTS_INTEGRATION_CPP := $(srcroot)test/integration/cpp/basic.cpp -else -CPP_SRCS := -TESTS_INTEGRATION_CPP := -endif -TESTS_STRESS := $(srcroot)test/stress/microbench.c \ - $(srcroot)test/stress/hookbench.c - - -TESTS := $(TESTS_UNIT) $(TESTS_INTEGRATION) $(TESTS_INTEGRATION_CPP) $(TESTS_STRESS) - -PRIVATE_NAMESPACE_HDRS := $(objroot)include/jemalloc/internal/private_namespace.h $(objroot)include/jemalloc/internal/private_namespace_jet.h -PRIVATE_NAMESPACE_GEN_HDRS := $(PRIVATE_NAMESPACE_HDRS:%.h=%.gen.h) -C_SYM_OBJS := $(C_SRCS:$(srcroot)%.c=$(objroot)%.sym.$(O)) -C_SYMS := $(C_SRCS:$(srcroot)%.c=$(objroot)%.sym) -C_OBJS := $(C_SRCS:$(srcroot)%.c=$(objroot)%.$(O)) -CPP_OBJS := $(CPP_SRCS:$(srcroot)%.cpp=$(objroot)%.$(O)) -C_PIC_OBJS := $(C_SRCS:$(srcroot)%.c=$(objroot)%.pic.$(O)) -CPP_PIC_OBJS := $(CPP_SRCS:$(srcroot)%.cpp=$(objroot)%.pic.$(O)) -C_JET_SYM_OBJS := $(C_SRCS:$(srcroot)%.c=$(objroot)%.jet.sym.$(O)) -C_JET_SYMS := $(C_SRCS:$(srcroot)%.c=$(objroot)%.jet.sym) -C_JET_OBJS := $(C_SRCS:$(srcroot)%.c=$(objroot)%.jet.$(O)) -C_TESTLIB_UNIT_OBJS := $(C_TESTLIB_SRCS:$(srcroot)%.c=$(objroot)%.unit.$(O)) -C_TESTLIB_INTEGRATION_OBJS := $(C_TESTLIB_SRCS:$(srcroot)%.c=$(objroot)%.integration.$(O)) -C_UTIL_INTEGRATION_OBJS := $(C_UTIL_INTEGRATION_SRCS:$(srcroot)%.c=$(objroot)%.integration.$(O)) -C_TESTLIB_STRESS_OBJS := $(C_TESTLIB_SRCS:$(srcroot)%.c=$(objroot)%.stress.$(O)) -C_TESTLIB_OBJS := $(C_TESTLIB_UNIT_OBJS) $(C_TESTLIB_INTEGRATION_OBJS) $(C_UTIL_INTEGRATION_OBJS) $(C_TESTLIB_STRESS_OBJS) - -TESTS_UNIT_OBJS := $(TESTS_UNIT:$(srcroot)%.c=$(objroot)%.$(O)) -TESTS_INTEGRATION_OBJS := $(TESTS_INTEGRATION:$(srcroot)%.c=$(objroot)%.$(O)) -TESTS_INTEGRATION_CPP_OBJS := $(TESTS_INTEGRATION_CPP:$(srcroot)%.cpp=$(objroot)%.$(O)) -TESTS_STRESS_OBJS := $(TESTS_STRESS:$(srcroot)%.c=$(objroot)%.$(O)) -TESTS_OBJS := $(TESTS_UNIT_OBJS) $(TESTS_INTEGRATION_OBJS) $(TESTS_STRESS_OBJS) -TESTS_CPP_OBJS := $(TESTS_INTEGRATION_CPP_OBJS) - -.PHONY: all dist build_doc_html build_doc_man build_doc -.PHONY: install_bin install_include install_lib -.PHONY: install_doc_html install_doc_man install_doc install -.PHONY: tests check clean distclean relclean - -.SECONDARY : $(PRIVATE_NAMESPACE_GEN_HDRS) $(TESTS_OBJS) $(TESTS_CPP_OBJS) - -# Default target. -all: build_lib - -dist: build_doc - -$(objroot)doc/%.html : $(objroot)doc/%.xml $(srcroot)doc/stylesheet.xsl $(objroot)doc/html.xsl -ifneq ($(XSLROOT),) - $(XSLTPROC) -o $@ $(objroot)doc/html.xsl $< -else -ifeq ($(wildcard $(DOCS_HTML)),) - @echo "<p>Missing xsltproc. Doc not built.</p>" > $@ -endif - @echo "Missing xsltproc. "$@" not (re)built." -endif - -$(objroot)doc/%.3 : $(objroot)doc/%.xml $(srcroot)doc/stylesheet.xsl $(objroot)doc/manpages.xsl -ifneq ($(XSLROOT),) - $(XSLTPROC) -o $@ $(objroot)doc/manpages.xsl $< -else -ifeq ($(wildcard $(DOCS_MAN3)),) - @echo "Missing xsltproc. Doc not built." > $@ -endif - @echo "Missing xsltproc. "$@" not (re)built." -endif - -build_doc_html: $(DOCS_HTML) -build_doc_man: $(DOCS_MAN3) -build_doc: $(DOCS) - -# -# Include generated dependency files. -# -ifdef CC_MM --include $(C_SYM_OBJS:%.$(O)=%.d) --include $(C_OBJS:%.$(O)=%.d) --include $(CPP_OBJS:%.$(O)=%.d) --include $(C_PIC_OBJS:%.$(O)=%.d) --include $(CPP_PIC_OBJS:%.$(O)=%.d) --include $(C_JET_SYM_OBJS:%.$(O)=%.d) --include $(C_JET_OBJS:%.$(O)=%.d) --include $(C_TESTLIB_OBJS:%.$(O)=%.d) --include $(TESTS_OBJS:%.$(O)=%.d) --include $(TESTS_CPP_OBJS:%.$(O)=%.d) -endif - -$(C_SYM_OBJS): $(objroot)src/%.sym.$(O): $(srcroot)src/%.c -$(C_SYM_OBJS): CPPFLAGS += -DJEMALLOC_NO_PRIVATE_NAMESPACE -$(C_SYMS): $(objroot)src/%.sym: $(objroot)src/%.sym.$(O) -$(C_OBJS): $(objroot)src/%.$(O): $(srcroot)src/%.c -$(CPP_OBJS): $(objroot)src/%.$(O): $(srcroot)src/%.cpp -$(C_PIC_OBJS): $(objroot)src/%.pic.$(O): $(srcroot)src/%.c -$(C_PIC_OBJS): CFLAGS += $(PIC_CFLAGS) -$(CPP_PIC_OBJS): $(objroot)src/%.pic.$(O): $(srcroot)src/%.cpp -$(CPP_PIC_OBJS): CXXFLAGS += $(PIC_CFLAGS) -$(C_JET_SYM_OBJS): $(objroot)src/%.jet.sym.$(O): $(srcroot)src/%.c -$(C_JET_SYM_OBJS): CPPFLAGS += -DJEMALLOC_JET -DJEMALLOC_NO_PRIVATE_NAMESPACE -$(C_JET_SYMS): $(objroot)src/%.jet.sym: $(objroot)src/%.jet.sym.$(O) -$(C_JET_OBJS): $(objroot)src/%.jet.$(O): $(srcroot)src/%.c -$(C_JET_OBJS): CPPFLAGS += -DJEMALLOC_JET -$(C_TESTLIB_UNIT_OBJS): $(objroot)test/src/%.unit.$(O): $(srcroot)test/src/%.c -$(C_TESTLIB_UNIT_OBJS): CPPFLAGS += -DJEMALLOC_UNIT_TEST -$(C_TESTLIB_INTEGRATION_OBJS): $(objroot)test/src/%.integration.$(O): $(srcroot)test/src/%.c -$(C_TESTLIB_INTEGRATION_OBJS): CPPFLAGS += -DJEMALLOC_INTEGRATION_TEST -$(C_UTIL_INTEGRATION_OBJS): $(objroot)src/%.integration.$(O): $(srcroot)src/%.c -$(C_TESTLIB_STRESS_OBJS): $(objroot)test/src/%.stress.$(O): $(srcroot)test/src/%.c -$(C_TESTLIB_STRESS_OBJS): CPPFLAGS += -DJEMALLOC_STRESS_TEST -DJEMALLOC_STRESS_TESTLIB -$(C_TESTLIB_OBJS): CPPFLAGS += -I$(srcroot)test/include -I$(objroot)test/include -$(TESTS_UNIT_OBJS): CPPFLAGS += -DJEMALLOC_UNIT_TEST -$(TESTS_INTEGRATION_OBJS): CPPFLAGS += -DJEMALLOC_INTEGRATION_TEST -$(TESTS_INTEGRATION_CPP_OBJS): CPPFLAGS += -DJEMALLOC_INTEGRATION_CPP_TEST -$(TESTS_STRESS_OBJS): CPPFLAGS += -DJEMALLOC_STRESS_TEST -$(TESTS_OBJS): $(objroot)test/%.$(O): $(srcroot)test/%.c -$(TESTS_CPP_OBJS): $(objroot)test/%.$(O): $(srcroot)test/%.cpp -$(TESTS_OBJS): CPPFLAGS += -I$(srcroot)test/include -I$(objroot)test/include -$(TESTS_CPP_OBJS): CPPFLAGS += -I$(srcroot)test/include -I$(objroot)test/include -ifneq ($(IMPORTLIB),$(SO)) -$(CPP_OBJS) $(C_SYM_OBJS) $(C_OBJS) $(C_JET_SYM_OBJS) $(C_JET_OBJS): CPPFLAGS += -DDLLEXPORT -endif - -# Dependencies. -ifndef CC_MM -HEADER_DIRS = $(srcroot)include/jemalloc/internal \ - $(objroot)include/jemalloc $(objroot)include/jemalloc/internal -HEADERS = $(filter-out $(PRIVATE_NAMESPACE_HDRS),$(wildcard $(foreach dir,$(HEADER_DIRS),$(dir)/*.h))) -$(C_SYM_OBJS) $(C_OBJS) $(CPP_OBJS) $(C_PIC_OBJS) $(CPP_PIC_OBJS) $(C_JET_SYM_OBJS) $(C_JET_OBJS) $(C_TESTLIB_OBJS) $(TESTS_OBJS) $(TESTS_CPP_OBJS): $(HEADERS) -$(TESTS_OBJS) $(TESTS_CPP_OBJS): $(objroot)test/include/test/jemalloc_test.h -endif - -$(C_OBJS) $(CPP_OBJS) $(C_PIC_OBJS) $(CPP_PIC_OBJS) $(C_TESTLIB_INTEGRATION_OBJS) $(C_UTIL_INTEGRATION_OBJS) $(TESTS_INTEGRATION_OBJS) $(TESTS_INTEGRATION_CPP_OBJS): $(objroot)include/jemalloc/internal/private_namespace.h -$(C_JET_OBJS) $(C_TESTLIB_UNIT_OBJS) $(C_TESTLIB_STRESS_OBJS) $(TESTS_UNIT_OBJS) $(TESTS_STRESS_OBJS): $(objroot)include/jemalloc/internal/private_namespace_jet.h - -$(C_SYM_OBJS) $(C_OBJS) $(C_PIC_OBJS) $(C_JET_SYM_OBJS) $(C_JET_OBJS) $(C_TESTLIB_OBJS) $(TESTS_OBJS): %.$(O): - @mkdir -p $(@D) - $(CC) $(CFLAGS) -c $(CPPFLAGS) $(CTARGET) $< -ifdef CC_MM - @$(CC) -MM $(CPPFLAGS) -MT $@ -o $(@:%.$(O)=%.d) $< -endif - -$(C_SYMS): %.sym: - @mkdir -p $(@D) - $(DUMP_SYMS) $< | $(AWK) -f $(objroot)include/jemalloc/internal/private_symbols.awk > $@ - -$(C_JET_SYMS): %.sym: - @mkdir -p $(@D) - $(DUMP_SYMS) $< | $(AWK) -f $(objroot)include/jemalloc/internal/private_symbols_jet.awk > $@ - -$(objroot)include/jemalloc/internal/private_namespace.gen.h: $(C_SYMS) - $(SHELL) $(srcroot)include/jemalloc/internal/private_namespace.sh $^ > $@ - -$(objroot)include/jemalloc/internal/private_namespace_jet.gen.h: $(C_JET_SYMS) - $(SHELL) $(srcroot)include/jemalloc/internal/private_namespace.sh $^ > $@ - -%.h: %.gen.h - @if ! `cmp -s $< $@` ; then echo "cp $< $<"; cp $< $@ ; fi - -$(CPP_OBJS) $(CPP_PIC_OBJS) $(TESTS_CPP_OBJS): %.$(O): - @mkdir -p $(@D) - $(CXX) $(CXXFLAGS) -c $(CPPFLAGS) $(CTARGET) $< -ifdef CC_MM - @$(CXX) -MM $(CPPFLAGS) -MT $@ -o $(@:%.$(O)=%.d) $< -endif - -ifneq ($(SOREV),$(SO)) -%.$(SO) : %.$(SOREV) - @mkdir -p $(@D) - ln -sf $(<F) $@ -endif - -$(objroot)lib/$(LIBJEMALLOC).$(SOREV) : $(if $(PIC_CFLAGS),$(C_PIC_OBJS),$(C_OBJS)) $(if $(PIC_CFLAGS),$(CPP_PIC_OBJS),$(CPP_OBJS)) - @mkdir -p $(@D) - $(CC) $(DSO_LDFLAGS) $(call RPATH,$(RPATH_EXTRA)) $(LDTARGET) $+ $(LDFLAGS) $(LIBS) $(EXTRA_LDFLAGS) - -$(objroot)lib/$(LIBJEMALLOC)_pic.$(A) : $(C_PIC_OBJS) $(CPP_PIC_OBJS) -$(objroot)lib/$(LIBJEMALLOC).$(A) : $(C_OBJS) $(CPP_OBJS) -$(objroot)lib/$(LIBJEMALLOC)_s.$(A) : $(C_OBJS) $(CPP_OBJS) - -$(STATIC_LIBS): - @mkdir -p $(@D) - $(AR) $(ARFLAGS)@AROUT@ $+ - -$(objroot)test/unit/%$(EXE): $(objroot)test/unit/%.$(O) $(C_JET_OBJS) $(C_TESTLIB_UNIT_OBJS) - @mkdir -p $(@D) - $(CC) $(LDTARGET) $(filter %.$(O),$^) $(call RPATH,$(objroot)lib) $(LDFLAGS) $(filter-out -lm,$(LIBS)) $(LM) $(EXTRA_LDFLAGS) - -$(objroot)test/integration/%$(EXE): $(objroot)test/integration/%.$(O) $(C_TESTLIB_INTEGRATION_OBJS) $(C_UTIL_INTEGRATION_OBJS) $(objroot)lib/$(LIBJEMALLOC).$(IMPORTLIB) - @mkdir -p $(@D) - $(CC) $(TEST_LD_MODE) $(LDTARGET) $(filter %.$(O),$^) $(call RPATH,$(objroot)lib) $(LJEMALLOC) $(LDFLAGS) $(filter-out -lm,$(filter -lrt -pthread -lstdc++,$(LIBS))) $(LM) $(EXTRA_LDFLAGS) - -$(objroot)test/integration/cpp/%$(EXE): $(objroot)test/integration/cpp/%.$(O) $(C_TESTLIB_INTEGRATION_OBJS) $(C_UTIL_INTEGRATION_OBJS) $(objroot)lib/$(LIBJEMALLOC).$(IMPORTLIB) - @mkdir -p $(@D) - $(CXX) $(LDTARGET) $(filter %.$(O),$^) $(call RPATH,$(objroot)lib) $(objroot)lib/$(LIBJEMALLOC).$(IMPORTLIB) $(LDFLAGS) $(filter-out -lm,$(LIBS)) -lm $(EXTRA_LDFLAGS) - -$(objroot)test/stress/%$(EXE): $(objroot)test/stress/%.$(O) $(C_JET_OBJS) $(C_TESTLIB_STRESS_OBJS) $(objroot)lib/$(LIBJEMALLOC).$(IMPORTLIB) - @mkdir -p $(@D) - $(CC) $(TEST_LD_MODE) $(LDTARGET) $(filter %.$(O),$^) $(call RPATH,$(objroot)lib) $(objroot)lib/$(LIBJEMALLOC).$(IMPORTLIB) $(LDFLAGS) $(filter-out -lm,$(LIBS)) $(LM) $(EXTRA_LDFLAGS) - -build_lib_shared: $(DSOS) -build_lib_static: $(STATIC_LIBS) -ifeq ($(enable_shared), 1) -build_lib: build_lib_shared -endif -ifeq ($(enable_static), 1) -build_lib: build_lib_static -endif - -install_bin: - $(INSTALL) -d $(BINDIR) - @for b in $(BINS); do \ - echo "$(INSTALL) -m 755 $$b $(BINDIR)"; \ - $(INSTALL) -m 755 $$b $(BINDIR); \ -done - -install_include: - $(INSTALL) -d $(INCLUDEDIR)/jemalloc - @for h in $(C_HDRS); do \ - echo "$(INSTALL) -m 644 $$h $(INCLUDEDIR)/jemalloc"; \ - $(INSTALL) -m 644 $$h $(INCLUDEDIR)/jemalloc; \ -done - -install_lib_shared: $(DSOS) - $(INSTALL) -d $(LIBDIR) - $(INSTALL) -m 755 $(objroot)lib/$(LIBJEMALLOC).$(SOREV) $(LIBDIR) -ifneq ($(SOREV),$(SO)) - ln -sf $(LIBJEMALLOC).$(SOREV) $(LIBDIR)/$(LIBJEMALLOC).$(SO) -endif - -install_lib_static: $(STATIC_LIBS) - $(INSTALL) -d $(LIBDIR) - @for l in $(STATIC_LIBS); do \ - echo "$(INSTALL) -m 755 $$l $(LIBDIR)"; \ - $(INSTALL) -m 755 $$l $(LIBDIR); \ -done - -install_lib_pc: $(PC) - $(INSTALL) -d $(LIBDIR)/pkgconfig - @for l in $(PC); do \ - echo "$(INSTALL) -m 644 $$l $(LIBDIR)/pkgconfig"; \ - $(INSTALL) -m 644 $$l $(LIBDIR)/pkgconfig; \ -done - -ifeq ($(enable_shared), 1) -install_lib: install_lib_shared -endif -ifeq ($(enable_static), 1) -install_lib: install_lib_static -endif -install_lib: install_lib_pc - -install_doc_html: - $(INSTALL) -d $(DATADIR)/doc/jemalloc$(install_suffix) - @for d in $(DOCS_HTML); do \ - echo "$(INSTALL) -m 644 $$d $(DATADIR)/doc/jemalloc$(install_suffix)"; \ - $(INSTALL) -m 644 $$d $(DATADIR)/doc/jemalloc$(install_suffix); \ -done - -install_doc_man: - $(INSTALL) -d $(MANDIR)/man3 - @for d in $(DOCS_MAN3); do \ - echo "$(INSTALL) -m 644 $$d $(MANDIR)/man3"; \ - $(INSTALL) -m 644 $$d $(MANDIR)/man3; \ -done - -install_doc: build_doc install_doc_html install_doc_man - -install: install_bin install_include install_lib - -ifeq ($(enable_doc), 1) -install: install_doc -endif - -tests_unit: $(TESTS_UNIT:$(srcroot)%.c=$(objroot)%$(EXE)) -tests_integration: $(TESTS_INTEGRATION:$(srcroot)%.c=$(objroot)%$(EXE)) $(TESTS_INTEGRATION_CPP:$(srcroot)%.cpp=$(objroot)%$(EXE)) -tests_stress: $(TESTS_STRESS:$(srcroot)%.c=$(objroot)%$(EXE)) -tests: tests_unit tests_integration tests_stress - -check_unit_dir: - @mkdir -p $(objroot)test/unit -check_integration_dir: - @mkdir -p $(objroot)test/integration -stress_dir: - @mkdir -p $(objroot)test/stress -check_dir: check_unit_dir check_integration_dir - -check_unit: tests_unit check_unit_dir - $(SHELL) $(objroot)test/test.sh $(TESTS_UNIT:$(srcroot)%.c=$(objroot)%) -check_integration_prof: tests_integration check_integration_dir -ifeq ($(enable_prof), 1) - $(MALLOC_CONF)="prof:true" $(SHELL) $(objroot)test/test.sh $(TESTS_INTEGRATION:$(srcroot)%.c=$(objroot)%) $(TESTS_INTEGRATION_CPP:$(srcroot)%.cpp=$(objroot)%) - $(MALLOC_CONF)="prof:true,prof_active:false" $(SHELL) $(objroot)test/test.sh $(TESTS_INTEGRATION:$(srcroot)%.c=$(objroot)%) $(TESTS_INTEGRATION_CPP:$(srcroot)%.cpp=$(objroot)%) -endif -check_integration_decay: tests_integration check_integration_dir - $(MALLOC_CONF)="dirty_decay_ms:-1,muzzy_decay_ms:-1" $(SHELL) $(objroot)test/test.sh $(TESTS_INTEGRATION:$(srcroot)%.c=$(objroot)%) $(TESTS_INTEGRATION_CPP:$(srcroot)%.cpp=$(objroot)%) - $(MALLOC_CONF)="dirty_decay_ms:0,muzzy_decay_ms:0" $(SHELL) $(objroot)test/test.sh $(TESTS_INTEGRATION:$(srcroot)%.c=$(objroot)%) $(TESTS_INTEGRATION_CPP:$(srcroot)%.cpp=$(objroot)%) -check_integration: tests_integration check_integration_dir - $(SHELL) $(objroot)test/test.sh $(TESTS_INTEGRATION:$(srcroot)%.c=$(objroot)%) $(TESTS_INTEGRATION_CPP:$(srcroot)%.cpp=$(objroot)%) -stress: tests_stress stress_dir - $(SHELL) $(objroot)test/test.sh $(TESTS_STRESS:$(srcroot)%.c=$(objroot)%) -check: check_unit check_integration check_integration_decay check_integration_prof - -clean: - rm -f $(PRIVATE_NAMESPACE_HDRS) - rm -f $(PRIVATE_NAMESPACE_GEN_HDRS) - rm -f $(C_SYM_OBJS) - rm -f $(C_SYMS) - rm -f $(C_OBJS) - rm -f $(CPP_OBJS) - rm -f $(C_PIC_OBJS) - rm -f $(CPP_PIC_OBJS) - rm -f $(C_JET_SYM_OBJS) - rm -f $(C_JET_SYMS) - rm -f $(C_JET_OBJS) - rm -f $(C_TESTLIB_OBJS) - rm -f $(C_SYM_OBJS:%.$(O)=%.d) - rm -f $(C_OBJS:%.$(O)=%.d) - rm -f $(CPP_OBJS:%.$(O)=%.d) - rm -f $(C_PIC_OBJS:%.$(O)=%.d) - rm -f $(CPP_PIC_OBJS:%.$(O)=%.d) - rm -f $(C_JET_SYM_OBJS:%.$(O)=%.d) - rm -f $(C_JET_OBJS:%.$(O)=%.d) - rm -f $(C_TESTLIB_OBJS:%.$(O)=%.d) - rm -f $(TESTS_OBJS:%.$(O)=%$(EXE)) - rm -f $(TESTS_OBJS) - rm -f $(TESTS_OBJS:%.$(O)=%.d) - rm -f $(TESTS_OBJS:%.$(O)=%.out) - rm -f $(TESTS_CPP_OBJS:%.$(O)=%$(EXE)) - rm -f $(TESTS_CPP_OBJS) - rm -f $(TESTS_CPP_OBJS:%.$(O)=%.d) - rm -f $(TESTS_CPP_OBJS:%.$(O)=%.out) - rm -f $(DSOS) $(STATIC_LIBS) - -distclean: clean - rm -f $(objroot)bin/jemalloc-config - rm -f $(objroot)bin/jemalloc.sh - rm -f $(objroot)bin/jeprof - rm -f $(objroot)config.log - rm -f $(objroot)config.status - rm -f $(objroot)config.stamp - rm -f $(cfghdrs_out) - rm -f $(cfgoutputs_out) - -relclean: distclean - rm -f $(objroot)configure - rm -f $(objroot)VERSION - rm -f $(DOCS_HTML) - rm -f $(DOCS_MAN3) - -#=============================================================================== -# Re-configuration rules. - -ifeq ($(enable_autogen), 1) -$(srcroot)configure : $(srcroot)configure.ac - cd ./$(srcroot) && $(AUTOCONF) - -$(objroot)config.status : $(srcroot)configure - ./$(objroot)config.status --recheck - -$(srcroot)config.stamp.in : $(srcroot)configure.ac - echo stamp > $(srcroot)config.stamp.in - -$(objroot)config.stamp : $(cfgoutputs_in) $(cfghdrs_in) $(srcroot)configure - ./$(objroot)config.status - @touch $@ - -# There must be some action in order for make to re-read Makefile when it is -# out of date. -$(cfgoutputs_out) $(cfghdrs_out) : $(objroot)config.stamp - @true -endif ->>>>>>> main diff --git a/contrib/jemalloc/TUNING.md b/contrib/jemalloc/TUNING.md index 500541dd52d0..e96399d7c9b8 100644 --- a/contrib/jemalloc/TUNING.md +++ b/contrib/jemalloc/TUNING.md @@ -1,4 +1,3 @@ -<<<<<<< HEAD This document summarizes the common approaches for performance fine tuning with jemalloc (as of 5.3.0). The default configuration of jemalloc tends to work reasonably well in practice, and most applications should not have to tune any @@ -128,135 +127,3 @@ improve application performance with jemalloc. access / allocation patterns. Threads with heavy workloads often benefit from explicit binding, e.g. binding very active threads to dedicated arenas may reduce contention at the allocator level. -||||||| dec341af7695 -======= -This document summarizes the common approaches for performance fine tuning with -jemalloc (as of 5.1.0). The default configuration of jemalloc tends to work -reasonably well in practice, and most applications should not have to tune any -options. However, in order to cover a wide range of applications and avoid -pathological cases, the default setting is sometimes kept conservative and -suboptimal, even for many common workloads. When jemalloc is properly tuned for -a specific application / workload, it is common to improve system level metrics -by a few percent, or make favorable trade-offs. - - -## Notable runtime options for performance tuning - -Runtime options can be set via -[malloc_conf](http://jemalloc.net/jemalloc.3.html#tuning). - -* [background_thread](http://jemalloc.net/jemalloc.3.html#background_thread) - - Enabling jemalloc background threads generally improves the tail latency for - application threads, since unused memory purging is shifted to the dedicated - background threads. In addition, unintended purging delay caused by - application inactivity is avoided with background threads. - - Suggested: `background_thread:true` when jemalloc managed threads can be - allowed. - -* [metadata_thp](http://jemalloc.net/jemalloc.3.html#opt.metadata_thp) - - Allowing jemalloc to utilize transparent huge pages for its internal - metadata usually reduces TLB misses significantly, especially for programs - with large memory footprint and frequent allocation / deallocation - activities. Metadata memory usage may increase due to the use of huge - pages. - - Suggested for allocation intensive programs: `metadata_thp:auto` or - `metadata_thp:always`, which is expected to improve CPU utilization at a - small memory cost. - -* [dirty_decay_ms](http://jemalloc.net/jemalloc.3.html#opt.dirty_decay_ms) and - [muzzy_decay_ms](http://jemalloc.net/jemalloc.3.html#opt.muzzy_decay_ms) - - Decay time determines how fast jemalloc returns unused pages back to the - operating system, and therefore provides a fairly straightforward trade-off - between CPU and memory usage. Shorter decay time purges unused pages faster - to reduces memory usage (usually at the cost of more CPU cycles spent on - purging), and vice versa. - - Suggested: tune the values based on the desired trade-offs. - -* [narenas](http://jemalloc.net/jemalloc.3.html#opt.narenas) - - By default jemalloc uses multiple arenas to reduce internal lock contention. - However high arena count may also increase overall memory fragmentation, - since arenas manage memory independently. When high degree of parallelism - is not expected at the allocator level, lower number of arenas often - improves memory usage. - - Suggested: if low parallelism is expected, try lower arena count while - monitoring CPU and memory usage. - -* [percpu_arena](http://jemalloc.net/jemalloc.3.html#opt.percpu_arena) - - Enable dynamic thread to arena association based on running CPU. This has - the potential to improve locality, e.g. when thread to CPU affinity is - present. - - Suggested: try `percpu_arena:percpu` or `percpu_arena:phycpu` if - thread migration between processors is expected to be infrequent. - -Examples: - -* High resource consumption application, prioritizing CPU utilization: - - `background_thread:true,metadata_thp:auto` combined with relaxed decay time - (increased `dirty_decay_ms` and / or `muzzy_decay_ms`, - e.g. `dirty_decay_ms:30000,muzzy_decay_ms:30000`). - -* High resource consumption application, prioritizing memory usage: - - `background_thread:true` combined with shorter decay time (decreased - `dirty_decay_ms` and / or `muzzy_decay_ms`, - e.g. `dirty_decay_ms:5000,muzzy_decay_ms:5000`), and lower arena count - (e.g. number of CPUs). - -* Low resource consumption application: - - `narenas:1,lg_tcache_max:13` combined with shorter decay time (decreased - `dirty_decay_ms` and / or `muzzy_decay_ms`,e.g. - `dirty_decay_ms:1000,muzzy_decay_ms:0`). - -* Extremely conservative -- minimize memory usage at all costs, only suitable when -allocation activity is very rare: - - `narenas:1,tcache:false,dirty_decay_ms:0,muzzy_decay_ms:0` - -Note that it is recommended to combine the options with `abort_conf:true` which -aborts immediately on illegal options. - -## Beyond runtime options - -In addition to the runtime options, there are a number of programmatic ways to -improve application performance with jemalloc. - -* [Explicit arenas](http://jemalloc.net/jemalloc.3.html#arenas.create) - - Manually created arenas can help performance in various ways, e.g. by - managing locality and contention for specific usages. For example, - applications can explicitly allocate frequently accessed objects from a - dedicated arena with - [mallocx()](http://jemalloc.net/jemalloc.3.html#MALLOCX_ARENA) to improve - locality. In addition, explicit arenas often benefit from individually - tuned options, e.g. relaxed [decay - time](http://jemalloc.net/jemalloc.3.html#arena.i.dirty_decay_ms) if - frequent reuse is expected. - -* [Extent hooks](http://jemalloc.net/jemalloc.3.html#arena.i.extent_hooks) - - Extent hooks allow customization for managing underlying memory. One use - case for performance purpose is to utilize huge pages -- for example, - [HHVM](https://github.com/facebook/hhvm/blob/master/hphp/util/alloc.cpp) - uses explicit arenas with customized extent hooks to manage 1GB huge pages - for frequently accessed data, which reduces TLB misses significantly. - -* [Explicit thread-to-arena - binding](http://jemalloc.net/jemalloc.3.html#thread.arena) - - It is common for some threads in an application to have different memory - access / allocation patterns. Threads with heavy workloads often benefit - from explicit binding, e.g. binding very active threads to dedicated arenas - may reduce contention at the allocator level. ->>>>>>> main diff --git a/contrib/jemalloc/bin/jeprof.in b/contrib/jemalloc/bin/jeprof.in index dc2c3ea877b8..dbf6252b921e 100644 --- a/contrib/jemalloc/bin/jeprof.in +++ b/contrib/jemalloc/bin/jeprof.in @@ -1,4 +1,3 @@ -<<<<<<< HEAD #! /usr/bin/env perl # Copyright (c) 1998-2007, Google Inc. @@ -5722,5631 +5721,3 @@ sub RunUnitTests { } exit ($error_count); } -||||||| dec341af7695 -======= -#! /usr/bin/env perl - -# Copyright (c) 1998-2007, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -# --- -# Program for printing the profile generated by common/profiler.cc, -# or by the heap profiler (common/debugallocation.cc) -# -# The profile contains a sequence of entries of the form: -# <count> <stack trace> -# This program parses the profile, and generates user-readable -# output. -# -# Examples: -# -# % tools/jeprof "program" "profile" -# Enters "interactive" mode -# -# % tools/jeprof --text "program" "profile" -# Generates one line per procedure -# -# % tools/jeprof --gv "program" "profile" -# Generates annotated call-graph and displays via "gv" -# -# % tools/jeprof --gv --focus=Mutex "program" "profile" -# Restrict to code paths that involve an entry that matches "Mutex" -# -# % tools/jeprof --gv --focus=Mutex --ignore=string "program" "profile" -# Restrict to code paths that involve an entry that matches "Mutex" -# and does not match "string" -# -# % tools/jeprof --list=IBF_CheckDocid "program" "profile" -# Generates disassembly listing of all routines with at least one -# sample that match the --list=<regexp> pattern. The listing is -# annotated with the flat and cumulative sample counts at each line. -# -# % tools/jeprof --disasm=IBF_CheckDocid "program" "profile" -# Generates disassembly listing of all routines with at least one -# sample that match the --disasm=<regexp> pattern. The listing is -# annotated with the flat and cumulative sample counts at each PC value. -# -# TODO: Use color to indicate files? - -use strict; -use warnings; -use Getopt::Long; -use Cwd; - -my $JEPROF_VERSION = "@jemalloc_version@"; -my $PPROF_VERSION = "2.0"; - -# These are the object tools we use which can come from a -# user-specified location using --tools, from the JEPROF_TOOLS -# environment variable, or from the environment. -my %obj_tool_map = ( - "objdump" => "objdump", - "nm" => "nm", - "addr2line" => "addr2line", - "c++filt" => "c++filt", - ## ConfigureObjTools may add architecture-specific entries: - #"nm_pdb" => "nm-pdb", # for reading windows (PDB-format) executables - #"addr2line_pdb" => "addr2line-pdb", # ditto - #"otool" => "otool", # equivalent of objdump on OS X -); -# NOTE: these are lists, so you can put in commandline flags if you want. -my @DOT = ("dot"); # leave non-absolute, since it may be in /usr/local -my @GV = ("gv"); -my @EVINCE = ("evince"); # could also be xpdf or perhaps acroread -my @KCACHEGRIND = ("kcachegrind"); -my @PS2PDF = ("ps2pdf"); -# These are used for dynamic profiles -my @URL_FETCHER = ("curl", "-s", "--fail"); - -# These are the web pages that servers need to support for dynamic profiles -my $HEAP_PAGE = "/pprof/heap"; -my $PROFILE_PAGE = "/pprof/profile"; # must support cgi-param "?seconds=#" -my $PMUPROFILE_PAGE = "/pprof/pmuprofile(?:\\?.*)?"; # must support cgi-param - # ?seconds=#&event=x&period=n -my $GROWTH_PAGE = "/pprof/growth"; -my $CONTENTION_PAGE = "/pprof/contention"; -my $WALL_PAGE = "/pprof/wall(?:\\?.*)?"; # accepts options like namefilter -my $FILTEREDPROFILE_PAGE = "/pprof/filteredprofile(?:\\?.*)?"; -my $CENSUSPROFILE_PAGE = "/pprof/censusprofile(?:\\?.*)?"; # must support cgi-param - # "?seconds=#", - # "?tags_regexp=#" and - # "?type=#". -my $SYMBOL_PAGE = "/pprof/symbol"; # must support symbol lookup via POST -my $PROGRAM_NAME_PAGE = "/pprof/cmdline"; - -# These are the web pages that can be named on the command line. -# All the alternatives must begin with /. -my $PROFILES = "($HEAP_PAGE|$PROFILE_PAGE|$PMUPROFILE_PAGE|" . - "$GROWTH_PAGE|$CONTENTION_PAGE|$WALL_PAGE|" . - "$FILTEREDPROFILE_PAGE|$CENSUSPROFILE_PAGE)"; - -# default binary name -my $UNKNOWN_BINARY = "(unknown)"; - -# There is a pervasive dependency on the length (in hex characters, -# i.e., nibbles) of an address, distinguishing between 32-bit and -# 64-bit profiles. To err on the safe size, default to 64-bit here: -my $address_length = 16; - -my $dev_null = "/dev/null"; -if (! -e $dev_null && $^O =~ /MSWin/) { # $^O is the OS perl was built for - $dev_null = "nul"; -} - -# A list of paths to search for shared object files -my @prefix_list = (); - -# Special routine name that should not have any symbols. -# Used as separator to parse "addr2line -i" output. -my $sep_symbol = '_fini'; -my $sep_address = undef; - -##### Argument parsing ##### - -sub usage_string { - return <<EOF; -Usage: -jeprof [options] <program> <profiles> - <profiles> is a space separated list of profile names. -jeprof [options] <symbolized-profiles> - <symbolized-profiles> is a list of profile files where each file contains - the necessary symbol mappings as well as profile data (likely generated - with --raw). -jeprof [options] <profile> - <profile> is a remote form. Symbols are obtained from host:port$SYMBOL_PAGE - - Each name can be: - /path/to/profile - a path to a profile file - host:port[/<service>] - a location of a service to get profile from - - The /<service> can be $HEAP_PAGE, $PROFILE_PAGE, /pprof/pmuprofile, - $GROWTH_PAGE, $CONTENTION_PAGE, /pprof/wall, - $CENSUSPROFILE_PAGE, or /pprof/filteredprofile. - For instance: - jeprof http://myserver.com:80$HEAP_PAGE - If /<service> is omitted, the service defaults to $PROFILE_PAGE (cpu profiling). -jeprof --symbols <program> - Maps addresses to symbol names. In this mode, stdin should be a - list of library mappings, in the same format as is found in the heap- - and cpu-profile files (this loosely matches that of /proc/self/maps - on linux), followed by a list of hex addresses to map, one per line. - - For more help with querying remote servers, including how to add the - necessary server-side support code, see this filename (or one like it): - - /usr/doc/gperftools-$PPROF_VERSION/pprof_remote_servers.html - -Options: - --cum Sort by cumulative data - --base=<base> Subtract <base> from <profile> before display - --interactive Run in interactive mode (interactive "help" gives help) [default] - --seconds=<n> Length of time for dynamic profiles [default=30 secs] - --add_lib=<file> Read additional symbols and line info from the given library - --lib_prefix=<dir> Comma separated list of library path prefixes - -Reporting Granularity: - --addresses Report at address level - --lines Report at source line level - --functions Report at function level [default] - --files Report at source file level - -Output type: - --text Generate text report - --callgrind Generate callgrind format to stdout - --gv Generate Postscript and display - --evince Generate PDF and display - --web Generate SVG and display - --list=<regexp> Generate source listing of matching routines - --disasm=<regexp> Generate disassembly of matching routines - --symbols Print demangled symbol names found at given addresses - --dot Generate DOT file to stdout - --ps Generate Postcript to stdout - --pdf Generate PDF to stdout - --svg Generate SVG to stdout - --gif Generate GIF to stdout - --raw Generate symbolized jeprof data (useful with remote fetch) - -Heap-Profile Options: - --inuse_space Display in-use (mega)bytes [default] - --inuse_objects Display in-use objects - --alloc_space Display allocated (mega)bytes - --alloc_objects Display allocated objects - --show_bytes Display space in bytes - --drop_negative Ignore negative differences - -Contention-profile options: - --total_delay Display total delay at each region [default] - --contentions Display number of delays at each region - --mean_delay Display mean delay at each region - -Call-graph Options: - --nodecount=<n> Show at most so many nodes [default=80] - --nodefraction=<f> Hide nodes below <f>*total [default=.005] - --edgefraction=<f> Hide edges below <f>*total [default=.001] - --maxdegree=<n> Max incoming/outgoing edges per node [default=8] - --focus=<regexp> Focus on backtraces with nodes matching <regexp> - --thread=<n> Show profile for thread <n> - --ignore=<regexp> Ignore backtraces with nodes matching <regexp> - --scale=<n> Set GV scaling [default=0] - --heapcheck Make nodes with non-0 object counts - (i.e. direct leak generators) more visible - --retain=<regexp> Retain only nodes that match <regexp> - --exclude=<regexp> Exclude all nodes that match <regexp> - -Miscellaneous: - --tools=<prefix or binary:fullpath>[,...] \$PATH for object tool pathnames - --test Run unit tests - --help This message - --version Version information - -Environment Variables: - JEPROF_TMPDIR Profiles directory. Defaults to \$HOME/jeprof - JEPROF_TOOLS Prefix for object tools pathnames - -Examples: - -jeprof /bin/ls ls.prof - Enters "interactive" mode -jeprof --text /bin/ls ls.prof - Outputs one line per procedure -jeprof --web /bin/ls ls.prof - Displays annotated call-graph in web browser -jeprof --gv /bin/ls ls.prof - Displays annotated call-graph via 'gv' -jeprof --gv --focus=Mutex /bin/ls ls.prof - Restricts to code paths including a .*Mutex.* entry -jeprof --gv --focus=Mutex --ignore=string /bin/ls ls.prof - Code paths including Mutex but not string -jeprof --list=getdir /bin/ls ls.prof - (Per-line) annotated source listing for getdir() -jeprof --disasm=getdir /bin/ls ls.prof - (Per-PC) annotated disassembly for getdir() - -jeprof http://localhost:1234/ - Enters "interactive" mode -jeprof --text localhost:1234 - Outputs one line per procedure for localhost:1234 -jeprof --raw localhost:1234 > ./local.raw -jeprof --text ./local.raw - Fetches a remote profile for later analysis and then - analyzes it in text mode. -EOF -} - -sub version_string { - return <<EOF -jeprof (part of jemalloc $JEPROF_VERSION) -based on pprof (part of gperftools $PPROF_VERSION) - -Copyright 1998-2007 Google Inc. - -This is BSD licensed software; see the source for copying conditions -and license information. -There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A -PARTICULAR PURPOSE. -EOF -} - -sub usage { - my $msg = shift; - print STDERR "$msg\n\n"; - print STDERR usage_string(); - print STDERR "\nFATAL ERROR: $msg\n"; # just as a reminder - exit(1); -} - -sub Init() { - # Setup tmp-file name and handler to clean it up. - # We do this in the very beginning so that we can use - # error() and cleanup() function anytime here after. - $main::tmpfile_sym = "/tmp/jeprof$$.sym"; - $main::tmpfile_ps = "/tmp/jeprof$$"; - $main::next_tmpfile = 0; - $SIG{'INT'} = \&sighandler; - - # Cache from filename/linenumber to source code - $main::source_cache = (); - - $main::opt_help = 0; - $main::opt_version = 0; - - $main::opt_cum = 0; - $main::opt_base = ''; - $main::opt_addresses = 0; - $main::opt_lines = 0; - $main::opt_functions = 0; - $main::opt_files = 0; - $main::opt_lib_prefix = ""; - - $main::opt_text = 0; - $main::opt_callgrind = 0; - $main::opt_list = ""; - $main::opt_disasm = ""; - $main::opt_symbols = 0; - $main::opt_gv = 0; - $main::opt_evince = 0; - $main::opt_web = 0; - $main::opt_dot = 0; - $main::opt_ps = 0; - $main::opt_pdf = 0; - $main::opt_gif = 0; - $main::opt_svg = 0; - $main::opt_raw = 0; - - $main::opt_nodecount = 80; - $main::opt_nodefraction = 0.005; - $main::opt_edgefraction = 0.001; - $main::opt_maxdegree = 8; - $main::opt_focus = ''; - $main::opt_thread = undef; - $main::opt_ignore = ''; - $main::opt_scale = 0; - $main::opt_heapcheck = 0; - $main::opt_retain = ''; - $main::opt_exclude = ''; - $main::opt_seconds = 30; - $main::opt_lib = ""; - - $main::opt_inuse_space = 0; - $main::opt_inuse_objects = 0; - $main::opt_alloc_space = 0; - $main::opt_alloc_objects = 0; - $main::opt_show_bytes = 0; - $main::opt_drop_negative = 0; - $main::opt_interactive = 0; - - $main::opt_total_delay = 0; - $main::opt_contentions = 0; - $main::opt_mean_delay = 0; - - $main::opt_tools = ""; - $main::opt_debug = 0; - $main::opt_test = 0; - - # These are undocumented flags used only by unittests. - $main::opt_test_stride = 0; - - # Are we using $SYMBOL_PAGE? - $main::use_symbol_page = 0; - - # Files returned by TempName. - %main::tempnames = (); - - # Type of profile we are dealing with - # Supported types: - # cpu - # heap - # growth - # contention - $main::profile_type = ''; # Empty type means "unknown" - - GetOptions("help!" => \$main::opt_help, - "version!" => \$main::opt_version, - "cum!" => \$main::opt_cum, - "base=s" => \$main::opt_base, - "seconds=i" => \$main::opt_seconds, - "add_lib=s" => \$main::opt_lib, - "lib_prefix=s" => \$main::opt_lib_prefix, - "functions!" => \$main::opt_functions, - "lines!" => \$main::opt_lines, - "addresses!" => \$main::opt_addresses, - "files!" => \$main::opt_files, - "text!" => \$main::opt_text, - "callgrind!" => \$main::opt_callgrind, - "list=s" => \$main::opt_list, - "disasm=s" => \$main::opt_disasm, - "symbols!" => \$main::opt_symbols, - "gv!" => \$main::opt_gv, - "evince!" => \$main::opt_evince, - "web!" => \$main::opt_web, - "dot!" => \$main::opt_dot, - "ps!" => \$main::opt_ps, - "pdf!" => \$main::opt_pdf, - "svg!" => \$main::opt_svg, - "gif!" => \$main::opt_gif, - "raw!" => \$main::opt_raw, - "interactive!" => \$main::opt_interactive, - "nodecount=i" => \$main::opt_nodecount, - "nodefraction=f" => \$main::opt_nodefraction, - "edgefraction=f" => \$main::opt_edgefraction, - "maxdegree=i" => \$main::opt_maxdegree, - "focus=s" => \$main::opt_focus, - "thread=s" => \$main::opt_thread, - "ignore=s" => \$main::opt_ignore, - "scale=i" => \$main::opt_scale, - "heapcheck" => \$main::opt_heapcheck, - "retain=s" => \$main::opt_retain, - "exclude=s" => \$main::opt_exclude, - "inuse_space!" => \$main::opt_inuse_space, - "inuse_objects!" => \$main::opt_inuse_objects, - "alloc_space!" => \$main::opt_alloc_space, - "alloc_objects!" => \$main::opt_alloc_objects, - "show_bytes!" => \$main::opt_show_bytes, - "drop_negative!" => \$main::opt_drop_negative, - "total_delay!" => \$main::opt_total_delay, - "contentions!" => \$main::opt_contentions, - "mean_delay!" => \$main::opt_mean_delay, - "tools=s" => \$main::opt_tools, - "test!" => \$main::opt_test, - "debug!" => \$main::opt_debug, - # Undocumented flags used only by unittests: - "test_stride=i" => \$main::opt_test_stride, - ) || usage("Invalid option(s)"); - - # Deal with the standard --help and --version - if ($main::opt_help) { - print usage_string(); - exit(0); - } - - if ($main::opt_version) { - print version_string(); - exit(0); - } - - # Disassembly/listing/symbols mode requires address-level info - if ($main::opt_disasm || $main::opt_list || $main::opt_symbols) { - $main::opt_functions = 0; - $main::opt_lines = 0; - $main::opt_addresses = 1; - $main::opt_files = 0; - } - - # Check heap-profiling flags - if ($main::opt_inuse_space + - $main::opt_inuse_objects + - $main::opt_alloc_space + - $main::opt_alloc_objects > 1) { - usage("Specify at most on of --inuse/--alloc options"); - } - - # Check output granularities - my $grains = - $main::opt_functions + - $main::opt_lines + - $main::opt_addresses + - $main::opt_files + - 0; - if ($grains > 1) { - usage("Only specify one output granularity option"); - } - if ($grains == 0) { - $main::opt_functions = 1; - } - - # Check output modes - my $modes = - $main::opt_text + - $main::opt_callgrind + - ($main::opt_list eq '' ? 0 : 1) + - ($main::opt_disasm eq '' ? 0 : 1) + - ($main::opt_symbols == 0 ? 0 : 1) + - $main::opt_gv + - $main::opt_evince + - $main::opt_web + - $main::opt_dot + - $main::opt_ps + - $main::opt_pdf + - $main::opt_svg + - $main::opt_gif + - $main::opt_raw + - $main::opt_interactive + - 0; - if ($modes > 1) { - usage("Only specify one output mode"); - } - if ($modes == 0) { - if (-t STDOUT) { # If STDOUT is a tty, activate interactive mode - $main::opt_interactive = 1; - } else { - $main::opt_text = 1; - } - } - - if ($main::opt_test) { - RunUnitTests(); - # Should not return - exit(1); - } - - # Binary name and profile arguments list - $main::prog = ""; - @main::pfile_args = (); - - # Remote profiling without a binary (using $SYMBOL_PAGE instead) - if (@ARGV > 0) { - if (IsProfileURL($ARGV[0])) { - $main::use_symbol_page = 1; - } elsif (IsSymbolizedProfileFile($ARGV[0])) { - $main::use_symbolized_profile = 1; - $main::prog = $UNKNOWN_BINARY; # will be set later from the profile file - } - } - - if ($main::use_symbol_page || $main::use_symbolized_profile) { - # We don't need a binary! - my %disabled = ('--lines' => $main::opt_lines, - '--disasm' => $main::opt_disasm); - for my $option (keys %disabled) { - usage("$option cannot be used without a binary") if $disabled{$option}; - } - # Set $main::prog later... - scalar(@ARGV) || usage("Did not specify profile file"); - } elsif ($main::opt_symbols) { - # --symbols needs a binary-name (to run nm on, etc) but not profiles - $main::prog = shift(@ARGV) || usage("Did not specify program"); - } else { - $main::prog = shift(@ARGV) || usage("Did not specify program"); - scalar(@ARGV) || usage("Did not specify profile file"); - } - - # Parse profile file/location arguments - foreach my $farg (@ARGV) { - if ($farg =~ m/(.*)\@([0-9]+)(|\/.*)$/ ) { - my $machine = $1; - my $num_machines = $2; - my $path = $3; - for (my $i = 0; $i < $num_machines; $i++) { - unshift(@main::pfile_args, "$i.$machine$path"); - } - } else { - unshift(@main::pfile_args, $farg); - } - } - - if ($main::use_symbol_page) { - unless (IsProfileURL($main::pfile_args[0])) { - error("The first profile should be a remote form to use $SYMBOL_PAGE\n"); - } - CheckSymbolPage(); - $main::prog = FetchProgramName(); - } elsif (!$main::use_symbolized_profile) { # may not need objtools! - ConfigureObjTools($main::prog) - } - - # Break the opt_lib_prefix into the prefix_list array - @prefix_list = split (',', $main::opt_lib_prefix); - - # Remove trailing / from the prefixes, in the list to prevent - # searching things like /my/path//lib/mylib.so - foreach (@prefix_list) { - s|/+$||; - } -} - -sub FilterAndPrint { - my ($profile, $symbols, $libs, $thread) = @_; - - # Get total data in profile - my $total = TotalProfile($profile); - - # Remove uniniteresting stack items - $profile = RemoveUninterestingFrames($symbols, $profile); - - # Focus? - if ($main::opt_focus ne '') { - $profile = FocusProfile($symbols, $profile, $main::opt_focus); - } - - # Ignore? - if ($main::opt_ignore ne '') { - $profile = IgnoreProfile($symbols, $profile, $main::opt_ignore); - } - - my $calls = ExtractCalls($symbols, $profile); - - # Reduce profiles to required output granularity, and also clean - # each stack trace so a given entry exists at most once. - my $reduced = ReduceProfile($symbols, $profile); - - # Get derived profiles - my $flat = FlatProfile($reduced); - my $cumulative = CumulativeProfile($reduced); - - # Print - if (!$main::opt_interactive) { - if ($main::opt_disasm) { - PrintDisassembly($libs, $flat, $cumulative, $main::opt_disasm); - } elsif ($main::opt_list) { - PrintListing($total, $libs, $flat, $cumulative, $main::opt_list, 0); - } elsif ($main::opt_text) { - # Make sure the output is empty when have nothing to report - # (only matters when --heapcheck is given but we must be - # compatible with old branches that did not pass --heapcheck always): - if ($total != 0) { - printf("Total%s: %s %s\n", - (defined($thread) ? " (t$thread)" : ""), - Unparse($total), Units()); - } - PrintText($symbols, $flat, $cumulative, -1); - } elsif ($main::opt_raw) { - PrintSymbolizedProfile($symbols, $profile, $main::prog); - } elsif ($main::opt_callgrind) { - PrintCallgrind($calls); - } else { - if (PrintDot($main::prog, $symbols, $profile, $flat, $cumulative, $total)) { - if ($main::opt_gv) { - RunGV(TempName($main::next_tmpfile, "ps"), ""); - } elsif ($main::opt_evince) { - RunEvince(TempName($main::next_tmpfile, "pdf"), ""); - } elsif ($main::opt_web) { - my $tmp = TempName($main::next_tmpfile, "svg"); - RunWeb($tmp); - # The command we run might hand the file name off - # to an already running browser instance and then exit. - # Normally, we'd remove $tmp on exit (right now), - # but fork a child to remove $tmp a little later, so that the - # browser has time to load it first. - delete $main::tempnames{$tmp}; - if (fork() == 0) { - sleep 5; - unlink($tmp); - exit(0); - } - } - } else { - cleanup(); - exit(1); - } - } - } else { - InteractiveMode($profile, $symbols, $libs, $total); - } -} - -sub Main() { - Init(); - $main::collected_profile = undef; - @main::profile_files = (); - $main::op_time = time(); - - # Printing symbols is special and requires a lot less info that most. - if ($main::opt_symbols) { - PrintSymbols(*STDIN); # Get /proc/maps and symbols output from stdin - return; - } - - # Fetch all profile data - FetchDynamicProfiles(); - - # this will hold symbols that we read from the profile files - my $symbol_map = {}; - - # Read one profile, pick the last item on the list - my $data = ReadProfile($main::prog, pop(@main::profile_files)); - my $profile = $data->{profile}; - my $pcs = $data->{pcs}; - my $libs = $data->{libs}; # Info about main program and shared libraries - $symbol_map = MergeSymbols($symbol_map, $data->{symbols}); - - # Add additional profiles, if available. - if (scalar(@main::profile_files) > 0) { - foreach my $pname (@main::profile_files) { - my $data2 = ReadProfile($main::prog, $pname); - $profile = AddProfile($profile, $data2->{profile}); - $pcs = AddPcs($pcs, $data2->{pcs}); - $symbol_map = MergeSymbols($symbol_map, $data2->{symbols}); - } - } - - # Subtract base from profile, if specified - if ($main::opt_base ne '') { - my $base = ReadProfile($main::prog, $main::opt_base); - $profile = SubtractProfile($profile, $base->{profile}); - $pcs = AddPcs($pcs, $base->{pcs}); - $symbol_map = MergeSymbols($symbol_map, $base->{symbols}); - } - - # Collect symbols - my $symbols; - if ($main::use_symbolized_profile) { - $symbols = FetchSymbols($pcs, $symbol_map); - } elsif ($main::use_symbol_page) { - $symbols = FetchSymbols($pcs); - } else { - # TODO(csilvers): $libs uses the /proc/self/maps data from profile1, - # which may differ from the data from subsequent profiles, especially - # if they were run on different machines. Use appropriate libs for - # each pc somehow. - $symbols = ExtractSymbols($libs, $pcs); - } - - if (!defined($main::opt_thread)) { - FilterAndPrint($profile, $symbols, $libs); - } - if (defined($data->{threads})) { - foreach my $thread (sort { $a <=> $b } keys(%{$data->{threads}})) { - if (defined($main::opt_thread) && - ($main::opt_thread eq '*' || $main::opt_thread == $thread)) { - my $thread_profile = $data->{threads}{$thread}; - FilterAndPrint($thread_profile, $symbols, $libs, $thread); - } - } - } - - cleanup(); - exit(0); -} - -##### Entry Point ##### - -Main(); - -# Temporary code to detect if we're running on a Goobuntu system. -# These systems don't have the right stuff installed for the special -# Readline libraries to work, so as a temporary workaround, we default -# to using the normal stdio code, rather than the fancier readline-based -# code -sub ReadlineMightFail { - if (-e '/lib/libtermcap.so.2') { - return 0; # libtermcap exists, so readline should be okay - } else { - return 1; - } -} - -sub RunGV { - my $fname = shift; - my $bg = shift; # "" or " &" if we should run in background - if (!system(ShellEscape(@GV, "--version") . " >$dev_null 2>&1")) { - # Options using double dash are supported by this gv version. - # Also, turn on noantialias to better handle bug in gv for - # postscript files with large dimensions. - # TODO: Maybe we should not pass the --noantialias flag - # if the gv version is known to work properly without the flag. - system(ShellEscape(@GV, "--scale=$main::opt_scale", "--noantialias", $fname) - . $bg); - } else { - # Old gv version - only supports options that use single dash. - print STDERR ShellEscape(@GV, "-scale", $main::opt_scale) . "\n"; - system(ShellEscape(@GV, "-scale", "$main::opt_scale", $fname) . $bg); - } -} - -sub RunEvince { - my $fname = shift; - my $bg = shift; # "" or " &" if we should run in background - system(ShellEscape(@EVINCE, $fname) . $bg); -} - -sub RunWeb { - my $fname = shift; - print STDERR "Loading web page file:///$fname\n"; - - if (`uname` =~ /Darwin/) { - # OS X: open will use standard preference for SVG files. - system("/usr/bin/open", $fname); - return; - } - - # Some kind of Unix; try generic symlinks, then specific browsers. - # (Stop once we find one.) - # Works best if the browser is already running. - my @alt = ( - "/etc/alternatives/gnome-www-browser", - "/etc/alternatives/x-www-browser", - "google-chrome", - "firefox", - ); - foreach my $b (@alt) { - if (system($b, $fname) == 0) { - return; - } - } - - print STDERR "Could not load web browser.\n"; -} - -sub RunKcachegrind { - my $fname = shift; - my $bg = shift; # "" or " &" if we should run in background - print STDERR "Starting '@KCACHEGRIND " . $fname . $bg . "'\n"; - system(ShellEscape(@KCACHEGRIND, $fname) . $bg); -} - - -##### Interactive helper routines ##### - -sub InteractiveMode { - $| = 1; # Make output unbuffered for interactive mode - my ($orig_profile, $symbols, $libs, $total) = @_; - - print STDERR "Welcome to jeprof! For help, type 'help'.\n"; - - # Use ReadLine if it's installed and input comes from a console. - if ( -t STDIN && - !ReadlineMightFail() && - defined(eval {require Term::ReadLine}) ) { - my $term = new Term::ReadLine 'jeprof'; - while ( defined ($_ = $term->readline('(jeprof) '))) { - $term->addhistory($_) if /\S/; - if (!InteractiveCommand($orig_profile, $symbols, $libs, $total, $_)) { - last; # exit when we get an interactive command to quit - } - } - } else { # don't have readline - while (1) { - print STDERR "(jeprof) "; - $_ = <STDIN>; - last if ! defined $_ ; - s/\r//g; # turn windows-looking lines into unix-looking lines - - # Save some flags that might be reset by InteractiveCommand() - my $save_opt_lines = $main::opt_lines; - - if (!InteractiveCommand($orig_profile, $symbols, $libs, $total, $_)) { - last; # exit when we get an interactive command to quit - } - - # Restore flags - $main::opt_lines = $save_opt_lines; - } - } -} - -# Takes two args: orig profile, and command to run. -# Returns 1 if we should keep going, or 0 if we were asked to quit -sub InteractiveCommand { - my($orig_profile, $symbols, $libs, $total, $command) = @_; - $_ = $command; # just to make future m//'s easier - if (!defined($_)) { - print STDERR "\n"; - return 0; - } - if (m/^\s*quit/) { - return 0; - } - if (m/^\s*help/) { - InteractiveHelpMessage(); - return 1; - } - # Clear all the mode options -- mode is controlled by "$command" - $main::opt_text = 0; - $main::opt_callgrind = 0; - $main::opt_disasm = 0; - $main::opt_list = 0; - $main::opt_gv = 0; - $main::opt_evince = 0; - $main::opt_cum = 0; - - if (m/^\s*(text|top)(\d*)\s*(.*)/) { - $main::opt_text = 1; - - my $line_limit = ($2 ne "") ? int($2) : 10; - - my $routine; - my $ignore; - ($routine, $ignore) = ParseInteractiveArgs($3); - - my $profile = ProcessProfile($total, $orig_profile, $symbols, "", $ignore); - my $reduced = ReduceProfile($symbols, $profile); - - # Get derived profiles - my $flat = FlatProfile($reduced); - my $cumulative = CumulativeProfile($reduced); - - PrintText($symbols, $flat, $cumulative, $line_limit); - return 1; - } - if (m/^\s*callgrind\s*([^ \n]*)/) { - $main::opt_callgrind = 1; - - # Get derived profiles - my $calls = ExtractCalls($symbols, $orig_profile); - my $filename = $1; - if ( $1 eq '' ) { - $filename = TempName($main::next_tmpfile, "callgrind"); - } - PrintCallgrind($calls, $filename); - if ( $1 eq '' ) { - RunKcachegrind($filename, " & "); - $main::next_tmpfile++; - } - - return 1; - } - if (m/^\s*(web)?list\s*(.+)/) { - my $html = (defined($1) && ($1 eq "web")); - $main::opt_list = 1; - - my $routine; - my $ignore; - ($routine, $ignore) = ParseInteractiveArgs($2); - - my $profile = ProcessProfile($total, $orig_profile, $symbols, "", $ignore); - my $reduced = ReduceProfile($symbols, $profile); - - # Get derived profiles - my $flat = FlatProfile($reduced); - my $cumulative = CumulativeProfile($reduced); - - PrintListing($total, $libs, $flat, $cumulative, $routine, $html); - return 1; - } - if (m/^\s*disasm\s*(.+)/) { - $main::opt_disasm = 1; - - my $routine; - my $ignore; - ($routine, $ignore) = ParseInteractiveArgs($1); - - # Process current profile to account for various settings - my $profile = ProcessProfile($total, $orig_profile, $symbols, "", $ignore); - my $reduced = ReduceProfile($symbols, $profile); - - # Get derived profiles - my $flat = FlatProfile($reduced); - my $cumulative = CumulativeProfile($reduced); - - PrintDisassembly($libs, $flat, $cumulative, $routine); - return 1; - } - if (m/^\s*(gv|web|evince)\s*(.*)/) { - $main::opt_gv = 0; - $main::opt_evince = 0; - $main::opt_web = 0; - if ($1 eq "gv") { - $main::opt_gv = 1; - } elsif ($1 eq "evince") { - $main::opt_evince = 1; - } elsif ($1 eq "web") { - $main::opt_web = 1; - } - - my $focus; - my $ignore; - ($focus, $ignore) = ParseInteractiveArgs($2); - - # Process current profile to account for various settings - my $profile = ProcessProfile($total, $orig_profile, $symbols, - $focus, $ignore); - my $reduced = ReduceProfile($symbols, $profile); - - # Get derived profiles - my $flat = FlatProfile($reduced); - my $cumulative = CumulativeProfile($reduced); - - if (PrintDot($main::prog, $symbols, $profile, $flat, $cumulative, $total)) { - if ($main::opt_gv) { - RunGV(TempName($main::next_tmpfile, "ps"), " &"); - } elsif ($main::opt_evince) { - RunEvince(TempName($main::next_tmpfile, "pdf"), " &"); - } elsif ($main::opt_web) { - RunWeb(TempName($main::next_tmpfile, "svg")); - } - $main::next_tmpfile++; - } - return 1; - } - if (m/^\s*$/) { - return 1; - } - print STDERR "Unknown command: try 'help'.\n"; - return 1; -} - - -sub ProcessProfile { - my $total_count = shift; - my $orig_profile = shift; - my $symbols = shift; - my $focus = shift; - my $ignore = shift; - - # Process current profile to account for various settings - my $profile = $orig_profile; - printf("Total: %s %s\n", Unparse($total_count), Units()); - if ($focus ne '') { - $profile = FocusProfile($symbols, $profile, $focus); - my $focus_count = TotalProfile($profile); - printf("After focusing on '%s': %s %s of %s (%0.1f%%)\n", - $focus, - Unparse($focus_count), Units(), - Unparse($total_count), ($focus_count*100.0) / $total_count); - } - if ($ignore ne '') { - $profile = IgnoreProfile($symbols, $profile, $ignore); - my $ignore_count = TotalProfile($profile); - printf("After ignoring '%s': %s %s of %s (%0.1f%%)\n", - $ignore, - Unparse($ignore_count), Units(), - Unparse($total_count), - ($ignore_count*100.0) / $total_count); - } - - return $profile; -} - -sub InteractiveHelpMessage { - print STDERR <<ENDOFHELP; -Interactive jeprof mode - -Commands: - gv - gv [focus] [-ignore1] [-ignore2] - Show graphical hierarchical display of current profile. Without - any arguments, shows all samples in the profile. With the optional - "focus" argument, restricts the samples shown to just those where - the "focus" regular expression matches a routine name on the stack - trace. - - web - web [focus] [-ignore1] [-ignore2] - Like GV, but displays profile in your web browser instead of using - Ghostview. Works best if your web browser is already running. - To change the browser that gets used: - On Linux, set the /etc/alternatives/gnome-www-browser symlink. - On OS X, change the Finder association for SVG files. - - list [routine_regexp] [-ignore1] [-ignore2] - Show source listing of routines whose names match "routine_regexp" - - weblist [routine_regexp] [-ignore1] [-ignore2] - Displays a source listing of routines whose names match "routine_regexp" - in a web browser. You can click on source lines to view the - corresponding disassembly. - - top [--cum] [-ignore1] [-ignore2] - top20 [--cum] [-ignore1] [-ignore2] - top37 [--cum] [-ignore1] [-ignore2] - Show top lines ordered by flat profile count, or cumulative count - if --cum is specified. If a number is present after 'top', the - top K routines will be shown (defaults to showing the top 10) - - disasm [routine_regexp] [-ignore1] [-ignore2] - Show disassembly of routines whose names match "routine_regexp", - annotated with sample counts. - - callgrind - callgrind [filename] - Generates callgrind file. If no filename is given, kcachegrind is called. - - help - This listing - quit or ^D - End jeprof - -For commands that accept optional -ignore tags, samples where any routine in -the stack trace matches the regular expression in any of the -ignore -parameters will be ignored. - -Further pprof details are available at this location (or one similar): - - /usr/doc/gperftools-$PPROF_VERSION/cpu_profiler.html - /usr/doc/gperftools-$PPROF_VERSION/heap_profiler.html - -ENDOFHELP -} -sub ParseInteractiveArgs { - my $args = shift; - my $focus = ""; - my $ignore = ""; - my @x = split(/ +/, $args); - foreach $a (@x) { - if ($a =~ m/^(--|-)lines$/) { - $main::opt_lines = 1; - } elsif ($a =~ m/^(--|-)cum$/) { - $main::opt_cum = 1; - } elsif ($a =~ m/^-(.*)/) { - $ignore .= (($ignore ne "") ? "|" : "" ) . $1; - } else { - $focus .= (($focus ne "") ? "|" : "" ) . $a; - } - } - if ($ignore ne "") { - print STDERR "Ignoring samples in call stacks that match '$ignore'\n"; - } - return ($focus, $ignore); -} - -##### Output code ##### - -sub TempName { - my $fnum = shift; - my $ext = shift; - my $file = "$main::tmpfile_ps.$fnum.$ext"; - $main::tempnames{$file} = 1; - return $file; -} - -# Print profile data in packed binary format (64-bit) to standard out -sub PrintProfileData { - my $profile = shift; - - # print header (64-bit style) - # (zero) (header-size) (version) (sample-period) (zero) - print pack('L*', 0, 0, 3, 0, 0, 0, 1, 0, 0, 0); - - foreach my $k (keys(%{$profile})) { - my $count = $profile->{$k}; - my @addrs = split(/\n/, $k); - if ($#addrs >= 0) { - my $depth = $#addrs + 1; - # int(foo / 2**32) is the only reliable way to get rid of bottom - # 32 bits on both 32- and 64-bit systems. - print pack('L*', $count & 0xFFFFFFFF, int($count / 2**32)); - print pack('L*', $depth & 0xFFFFFFFF, int($depth / 2**32)); - - foreach my $full_addr (@addrs) { - my $addr = $full_addr; - $addr =~ s/0x0*//; # strip off leading 0x, zeroes - if (length($addr) > 16) { - print STDERR "Invalid address in profile: $full_addr\n"; - next; - } - my $low_addr = substr($addr, -8); # get last 8 hex chars - my $high_addr = substr($addr, -16, 8); # get up to 8 more hex chars - print pack('L*', hex('0x' . $low_addr), hex('0x' . $high_addr)); - } - } - } -} - -# Print symbols and profile data -sub PrintSymbolizedProfile { - my $symbols = shift; - my $profile = shift; - my $prog = shift; - - $SYMBOL_PAGE =~ m,[^/]+$,; # matches everything after the last slash - my $symbol_marker = $&; - - print '--- ', $symbol_marker, "\n"; - if (defined($prog)) { - print 'binary=', $prog, "\n"; - } - while (my ($pc, $name) = each(%{$symbols})) { - my $sep = ' '; - print '0x', $pc; - # We have a list of function names, which include the inlined - # calls. They are separated (and terminated) by --, which is - # illegal in function names. - for (my $j = 2; $j <= $#{$name}; $j += 3) { - print $sep, $name->[$j]; - $sep = '--'; - } - print "\n"; - } - print '---', "\n"; - - my $profile_marker; - if ($main::profile_type eq 'heap') { - $HEAP_PAGE =~ m,[^/]+$,; # matches everything after the last slash - $profile_marker = $&; - } elsif ($main::profile_type eq 'growth') { - $GROWTH_PAGE =~ m,[^/]+$,; # matches everything after the last slash - $profile_marker = $&; - } elsif ($main::profile_type eq 'contention') { - $CONTENTION_PAGE =~ m,[^/]+$,; # matches everything after the last slash - $profile_marker = $&; - } else { # elsif ($main::profile_type eq 'cpu') - $PROFILE_PAGE =~ m,[^/]+$,; # matches everything after the last slash - $profile_marker = $&; - } - - print '--- ', $profile_marker, "\n"; - if (defined($main::collected_profile)) { - # if used with remote fetch, simply dump the collected profile to output. - open(SRC, "<$main::collected_profile"); - while (<SRC>) { - print $_; - } - close(SRC); - } else { - # --raw/http: For everything to work correctly for non-remote profiles, we - # would need to extend PrintProfileData() to handle all possible profile - # types, re-enable the code that is currently disabled in ReadCPUProfile() - # and FixCallerAddresses(), and remove the remote profile dumping code in - # the block above. - die "--raw/http: jeprof can only dump remote profiles for --raw\n"; - # dump a cpu-format profile to standard out - PrintProfileData($profile); - } -} - -# Print text output -sub PrintText { - my $symbols = shift; - my $flat = shift; - my $cumulative = shift; - my $line_limit = shift; - - my $total = TotalProfile($flat); - - # Which profile to sort by? - my $s = $main::opt_cum ? $cumulative : $flat; - - my $running_sum = 0; - my $lines = 0; - foreach my $k (sort { GetEntry($s, $b) <=> GetEntry($s, $a) || $a cmp $b } - keys(%{$cumulative})) { - my $f = GetEntry($flat, $k); - my $c = GetEntry($cumulative, $k); - $running_sum += $f; - - my $sym = $k; - if (exists($symbols->{$k})) { - $sym = $symbols->{$k}->[0] . " " . $symbols->{$k}->[1]; - if ($main::opt_addresses) { - $sym = $k . " " . $sym; - } - } - - if ($f != 0 || $c != 0) { - printf("%8s %6s %6s %8s %6s %s\n", - Unparse($f), - Percent($f, $total), - Percent($running_sum, $total), - Unparse($c), - Percent($c, $total), - $sym); - } - $lines++; - last if ($line_limit >= 0 && $lines >= $line_limit); - } -} - -# Callgrind format has a compression for repeated function and file -# names. You show the name the first time, and just use its number -# subsequently. This can cut down the file to about a third or a -# quarter of its uncompressed size. $key and $val are the key/value -# pair that would normally be printed by callgrind; $map is a map from -# value to number. -sub CompressedCGName { - my($key, $val, $map) = @_; - my $idx = $map->{$val}; - # For very short keys, providing an index hurts rather than helps. - if (length($val) <= 3) { - return "$key=$val\n"; - } elsif (defined($idx)) { - return "$key=($idx)\n"; - } else { - # scalar(keys $map) gives the number of items in the map. - $idx = scalar(keys(%{$map})) + 1; - $map->{$val} = $idx; - return "$key=($idx) $val\n"; - } -} - -# Print the call graph in a way that's suiteable for callgrind. -sub PrintCallgrind { - my $calls = shift; - my $filename; - my %filename_to_index_map; - my %fnname_to_index_map; - - if ($main::opt_interactive) { - $filename = shift; - print STDERR "Writing callgrind file to '$filename'.\n" - } else { - $filename = "&STDOUT"; - } - open(CG, ">$filename"); - printf CG ("events: Hits\n\n"); - foreach my $call ( map { $_->[0] } - sort { $a->[1] cmp $b ->[1] || - $a->[2] <=> $b->[2] } - map { /([^:]+):(\d+):([^ ]+)( -> ([^:]+):(\d+):(.+))?/; - [$_, $1, $2] } - keys %$calls ) { - my $count = int($calls->{$call}); - $call =~ /([^:]+):(\d+):([^ ]+)( -> ([^:]+):(\d+):(.+))?/; - my ( $caller_file, $caller_line, $caller_function, - $callee_file, $callee_line, $callee_function ) = - ( $1, $2, $3, $5, $6, $7 ); - - # TODO(csilvers): for better compression, collect all the - # caller/callee_files and functions first, before printing - # anything, and only compress those referenced more than once. - printf CG CompressedCGName("fl", $caller_file, \%filename_to_index_map); - printf CG CompressedCGName("fn", $caller_function, \%fnname_to_index_map); - if (defined $6) { - printf CG CompressedCGName("cfl", $callee_file, \%filename_to_index_map); - printf CG CompressedCGName("cfn", $callee_function, \%fnname_to_index_map); - printf CG ("calls=$count $callee_line\n"); - } - printf CG ("$caller_line $count\n\n"); - } -} - -# Print disassembly for all all routines that match $main::opt_disasm -sub PrintDisassembly { - my $libs = shift; - my $flat = shift; - my $cumulative = shift; - my $disasm_opts = shift; - - my $total = TotalProfile($flat); - - foreach my $lib (@{$libs}) { - my $symbol_table = GetProcedureBoundaries($lib->[0], $disasm_opts); - my $offset = AddressSub($lib->[1], $lib->[3]); - foreach my $routine (sort ByName keys(%{$symbol_table})) { - my $start_addr = $symbol_table->{$routine}->[0]; - my $end_addr = $symbol_table->{$routine}->[1]; - # See if there are any samples in this routine - my $length = hex(AddressSub($end_addr, $start_addr)); - my $addr = AddressAdd($start_addr, $offset); - for (my $i = 0; $i < $length; $i++) { - if (defined($cumulative->{$addr})) { - PrintDisassembledFunction($lib->[0], $offset, - $routine, $flat, $cumulative, - $start_addr, $end_addr, $total); - last; - } - $addr = AddressInc($addr); - } - } - } -} - -# Return reference to array of tuples of the form: -# [start_address, filename, linenumber, instruction, limit_address] -# E.g., -# ["0x806c43d", "/foo/bar.cc", 131, "ret", "0x806c440"] -sub Disassemble { - my $prog = shift; - my $offset = shift; - my $start_addr = shift; - my $end_addr = shift; - - my $objdump = $obj_tool_map{"objdump"}; - my $cmd = ShellEscape($objdump, "-C", "-d", "-l", "--no-show-raw-insn", - "--start-address=0x$start_addr", - "--stop-address=0x$end_addr", $prog); - open(OBJDUMP, "$cmd |") || error("$cmd: $!\n"); - my @result = (); - my $filename = ""; - my $linenumber = -1; - my $last = ["", "", "", ""]; - while (<OBJDUMP>) { - s/\r//g; # turn windows-looking lines into unix-looking lines - chop; - if (m|\s*([^:\s]+):(\d+)\s*$|) { - # Location line of the form: - # <filename>:<linenumber> - $filename = $1; - $linenumber = $2; - } elsif (m/^ +([0-9a-f]+):\s*(.*)/) { - # Disassembly line -- zero-extend address to full length - my $addr = HexExtend($1); - my $k = AddressAdd($addr, $offset); - $last->[4] = $k; # Store ending address for previous instruction - $last = [$k, $filename, $linenumber, $2, $end_addr]; - push(@result, $last); - } - } - close(OBJDUMP); - return @result; -} - -# The input file should contain lines of the form /proc/maps-like -# output (same format as expected from the profiles) or that looks -# like hex addresses (like "0xDEADBEEF"). We will parse all -# /proc/maps output, and for all the hex addresses, we will output -# "short" symbol names, one per line, in the same order as the input. -sub PrintSymbols { - my $maps_and_symbols_file = shift; - - # ParseLibraries expects pcs to be in a set. Fine by us... - my @pclist = (); # pcs in sorted order - my $pcs = {}; - my $map = ""; - foreach my $line (<$maps_and_symbols_file>) { - $line =~ s/\r//g; # turn windows-looking lines into unix-looking lines - if ($line =~ /\b(0x[0-9a-f]+)\b/i) { - push(@pclist, HexExtend($1)); - $pcs->{$pclist[-1]} = 1; - } else { - $map .= $line; - } - } - - my $libs = ParseLibraries($main::prog, $map, $pcs); - my $symbols = ExtractSymbols($libs, $pcs); - - foreach my $pc (@pclist) { - # ->[0] is the shortname, ->[2] is the full name - print(($symbols->{$pc}->[0] || "??") . "\n"); - } -} - - -# For sorting functions by name -sub ByName { - return ShortFunctionName($a) cmp ShortFunctionName($b); -} - -# Print source-listing for all all routines that match $list_opts -sub PrintListing { - my $total = shift; - my $libs = shift; - my $flat = shift; - my $cumulative = shift; - my $list_opts = shift; - my $html = shift; - - my $output = \*STDOUT; - my $fname = ""; - - if ($html) { - # Arrange to write the output to a temporary file - $fname = TempName($main::next_tmpfile, "html"); - $main::next_tmpfile++; - if (!open(TEMP, ">$fname")) { - print STDERR "$fname: $!\n"; - return; - } - $output = \*TEMP; - print $output HtmlListingHeader(); - printf $output ("<div class=\"legend\">%s<br>Total: %s %s</div>\n", - $main::prog, Unparse($total), Units()); - } - - my $listed = 0; - foreach my $lib (@{$libs}) { - my $symbol_table = GetProcedureBoundaries($lib->[0], $list_opts); - my $offset = AddressSub($lib->[1], $lib->[3]); - foreach my $routine (sort ByName keys(%{$symbol_table})) { - # Print if there are any samples in this routine - my $start_addr = $symbol_table->{$routine}->[0]; - my $end_addr = $symbol_table->{$routine}->[1]; - my $length = hex(AddressSub($end_addr, $start_addr)); - my $addr = AddressAdd($start_addr, $offset); - for (my $i = 0; $i < $length; $i++) { - if (defined($cumulative->{$addr})) { - $listed += PrintSource( - $lib->[0], $offset, - $routine, $flat, $cumulative, - $start_addr, $end_addr, - $html, - $output); - last; - } - $addr = AddressInc($addr); - } - } - } - - if ($html) { - if ($listed > 0) { - print $output HtmlListingFooter(); - close($output); - RunWeb($fname); - } else { - close($output); - unlink($fname); - } - } -} - -sub HtmlListingHeader { - return <<'EOF'; -<DOCTYPE html> -<html> -<head> -<title>Pprof listing</title> -<style type="text/css"> -body { - font-family: sans-serif; -} -h1 { - font-size: 1.5em; - margin-bottom: 4px; -} -.legend { - font-size: 1.25em; -} -.line { - color: #aaaaaa; -} -.nop { - color: #aaaaaa; -} -.unimportant { - color: #cccccc; -} -.disasmloc { - color: #000000; -} -.deadsrc { - cursor: pointer; -} -.deadsrc:hover { - background-color: #eeeeee; -} -.livesrc { - color: #0000ff; - cursor: pointer; -} -.livesrc:hover { - background-color: #eeeeee; -} -.asm { - color: #008800; - display: none; -} -</style> -<script type="text/javascript"> -function jeprof_toggle_asm(e) { - var target; - if (!e) e = window.event; - if (e.target) target = e.target; - else if (e.srcElement) target = e.srcElement; - - if (target) { - var asm = target.nextSibling; - if (asm && asm.className == "asm") { - asm.style.display = (asm.style.display == "block" ? "" : "block"); - e.preventDefault(); - return false; - } - } -} -</script> -</head> -<body> -EOF -} - -sub HtmlListingFooter { - return <<'EOF'; -</body> -</html> -EOF -} - -sub HtmlEscape { - my $text = shift; - $text =~ s/&/&/g; - $text =~ s/</</g; - $text =~ s/>/>/g; - return $text; -} - -# Returns the indentation of the line, if it has any non-whitespace -# characters. Otherwise, returns -1. -sub Indentation { - my $line = shift; - if (m/^(\s*)\S/) { - return length($1); - } else { - return -1; - } -} - -# If the symbol table contains inlining info, Disassemble() may tag an -# instruction with a location inside an inlined function. But for -# source listings, we prefer to use the location in the function we -# are listing. So use MapToSymbols() to fetch full location -# information for each instruction and then pick out the first -# location from a location list (location list contains callers before -# callees in case of inlining). -# -# After this routine has run, each entry in $instructions contains: -# [0] start address -# [1] filename for function we are listing -# [2] line number for function we are listing -# [3] disassembly -# [4] limit address -# [5] most specific filename (may be different from [1] due to inlining) -# [6] most specific line number (may be different from [2] due to inlining) -sub GetTopLevelLineNumbers { - my ($lib, $offset, $instructions) = @_; - my $pcs = []; - for (my $i = 0; $i <= $#{$instructions}; $i++) { - push(@{$pcs}, $instructions->[$i]->[0]); - } - my $symbols = {}; - MapToSymbols($lib, $offset, $pcs, $symbols); - for (my $i = 0; $i <= $#{$instructions}; $i++) { - my $e = $instructions->[$i]; - push(@{$e}, $e->[1]); - push(@{$e}, $e->[2]); - my $addr = $e->[0]; - my $sym = $symbols->{$addr}; - if (defined($sym)) { - if ($#{$sym} >= 2 && $sym->[1] =~ m/^(.*):(\d+)$/) { - $e->[1] = $1; # File name - $e->[2] = $2; # Line number - } - } - } -} - -# Print source-listing for one routine -sub PrintSource { - my $prog = shift; - my $offset = shift; - my $routine = shift; - my $flat = shift; - my $cumulative = shift; - my $start_addr = shift; - my $end_addr = shift; - my $html = shift; - my $output = shift; - - # Disassemble all instructions (just to get line numbers) - my @instructions = Disassemble($prog, $offset, $start_addr, $end_addr); - GetTopLevelLineNumbers($prog, $offset, \@instructions); - - # Hack 1: assume that the first source file encountered in the - # disassembly contains the routine - my $filename = undef; - for (my $i = 0; $i <= $#instructions; $i++) { - if ($instructions[$i]->[2] >= 0) { - $filename = $instructions[$i]->[1]; - last; - } - } - if (!defined($filename)) { - print STDERR "no filename found in $routine\n"; - return 0; - } - - # Hack 2: assume that the largest line number from $filename is the - # end of the procedure. This is typically safe since if P1 contains - # an inlined call to P2, then P2 usually occurs earlier in the - # source file. If this does not work, we might have to compute a - # density profile or just print all regions we find. - my $lastline = 0; - for (my $i = 0; $i <= $#instructions; $i++) { - my $f = $instructions[$i]->[1]; - my $l = $instructions[$i]->[2]; - if (($f eq $filename) && ($l > $lastline)) { - $lastline = $l; - } - } - - # Hack 3: assume the first source location from "filename" is the start of - # the source code. - my $firstline = 1; - for (my $i = 0; $i <= $#instructions; $i++) { - if ($instructions[$i]->[1] eq $filename) { - $firstline = $instructions[$i]->[2]; - last; - } - } - - # Hack 4: Extend last line forward until its indentation is less than - # the indentation we saw on $firstline - my $oldlastline = $lastline; - { - if (!open(FILE, "<$filename")) { - print STDERR "$filename: $!\n"; - return 0; - } - my $l = 0; - my $first_indentation = -1; - while (<FILE>) { - s/\r//g; # turn windows-looking lines into unix-looking lines - $l++; - my $indent = Indentation($_); - if ($l >= $firstline) { - if ($first_indentation < 0 && $indent >= 0) { - $first_indentation = $indent; - last if ($first_indentation == 0); - } - } - if ($l >= $lastline && $indent >= 0) { - if ($indent >= $first_indentation) { - $lastline = $l+1; - } else { - last; - } - } - } - close(FILE); - } - - # Assign all samples to the range $firstline,$lastline, - # Hack 4: If an instruction does not occur in the range, its samples - # are moved to the next instruction that occurs in the range. - my $samples1 = {}; # Map from line number to flat count - my $samples2 = {}; # Map from line number to cumulative count - my $running1 = 0; # Unassigned flat counts - my $running2 = 0; # Unassigned cumulative counts - my $total1 = 0; # Total flat counts - my $total2 = 0; # Total cumulative counts - my %disasm = (); # Map from line number to disassembly - my $running_disasm = ""; # Unassigned disassembly - my $skip_marker = "---\n"; - if ($html) { - $skip_marker = ""; - for (my $l = $firstline; $l <= $lastline; $l++) { - $disasm{$l} = ""; - } - } - my $last_dis_filename = ''; - my $last_dis_linenum = -1; - my $last_touched_line = -1; # To detect gaps in disassembly for a line - foreach my $e (@instructions) { - # Add up counts for all address that fall inside this instruction - my $c1 = 0; - my $c2 = 0; - for (my $a = $e->[0]; $a lt $e->[4]; $a = AddressInc($a)) { - $c1 += GetEntry($flat, $a); - $c2 += GetEntry($cumulative, $a); - } - - if ($html) { - my $dis = sprintf(" %6s %6s \t\t%8s: %s ", - HtmlPrintNumber($c1), - HtmlPrintNumber($c2), - UnparseAddress($offset, $e->[0]), - CleanDisassembly($e->[3])); - - # Append the most specific source line associated with this instruction - if (length($dis) < 80) { $dis .= (' ' x (80 - length($dis))) }; - $dis = HtmlEscape($dis); - my $f = $e->[5]; - my $l = $e->[6]; - if ($f ne $last_dis_filename) { - $dis .= sprintf("<span class=disasmloc>%s:%d</span>", - HtmlEscape(CleanFileName($f)), $l); - } elsif ($l ne $last_dis_linenum) { - # De-emphasize the unchanged file name portion - $dis .= sprintf("<span class=unimportant>%s</span>" . - "<span class=disasmloc>:%d</span>", - HtmlEscape(CleanFileName($f)), $l); - } else { - # De-emphasize the entire location - $dis .= sprintf("<span class=unimportant>%s:%d</span>", - HtmlEscape(CleanFileName($f)), $l); - } - $last_dis_filename = $f; - $last_dis_linenum = $l; - $running_disasm .= $dis; - $running_disasm .= "\n"; - } - - $running1 += $c1; - $running2 += $c2; - $total1 += $c1; - $total2 += $c2; - my $file = $e->[1]; - my $line = $e->[2]; - if (($file eq $filename) && - ($line >= $firstline) && - ($line <= $lastline)) { - # Assign all accumulated samples to this line - AddEntry($samples1, $line, $running1); - AddEntry($samples2, $line, $running2); - $running1 = 0; - $running2 = 0; - if ($html) { - if ($line != $last_touched_line && $disasm{$line} ne '') { - $disasm{$line} .= "\n"; - } - $disasm{$line} .= $running_disasm; - $running_disasm = ''; - $last_touched_line = $line; - } - } - } - - # Assign any leftover samples to $lastline - AddEntry($samples1, $lastline, $running1); - AddEntry($samples2, $lastline, $running2); - if ($html) { - if ($lastline != $last_touched_line && $disasm{$lastline} ne '') { - $disasm{$lastline} .= "\n"; - } - $disasm{$lastline} .= $running_disasm; - } - - if ($html) { - printf $output ( - "<h1>%s</h1>%s\n<pre onClick=\"jeprof_toggle_asm()\">\n" . - "Total:%6s %6s (flat / cumulative %s)\n", - HtmlEscape(ShortFunctionName($routine)), - HtmlEscape(CleanFileName($filename)), - Unparse($total1), - Unparse($total2), - Units()); - } else { - printf $output ( - "ROUTINE ====================== %s in %s\n" . - "%6s %6s Total %s (flat / cumulative)\n", - ShortFunctionName($routine), - CleanFileName($filename), - Unparse($total1), - Unparse($total2), - Units()); - } - if (!open(FILE, "<$filename")) { - print STDERR "$filename: $!\n"; - return 0; - } - my $l = 0; - while (<FILE>) { - s/\r//g; # turn windows-looking lines into unix-looking lines - $l++; - if ($l >= $firstline - 5 && - (($l <= $oldlastline + 5) || ($l <= $lastline))) { - chop; - my $text = $_; - if ($l == $firstline) { print $output $skip_marker; } - my $n1 = GetEntry($samples1, $l); - my $n2 = GetEntry($samples2, $l); - if ($html) { - # Emit a span that has one of the following classes: - # livesrc -- has samples - # deadsrc -- has disassembly, but with no samples - # nop -- has no matching disasembly - # Also emit an optional span containing disassembly. - my $dis = $disasm{$l}; - my $asm = ""; - if (defined($dis) && $dis ne '') { - $asm = "<span class=\"asm\">" . $dis . "</span>"; - } - my $source_class = (($n1 + $n2 > 0) - ? "livesrc" - : (($asm ne "") ? "deadsrc" : "nop")); - printf $output ( - "<span class=\"line\">%5d</span> " . - "<span class=\"%s\">%6s %6s %s</span>%s\n", - $l, $source_class, - HtmlPrintNumber($n1), - HtmlPrintNumber($n2), - HtmlEscape($text), - $asm); - } else { - printf $output( - "%6s %6s %4d: %s\n", - UnparseAlt($n1), - UnparseAlt($n2), - $l, - $text); - } - if ($l == $lastline) { print $output $skip_marker; } - }; - } - close(FILE); - if ($html) { - print $output "</pre>\n"; - } - return 1; -} - -# Return the source line for the specified file/linenumber. -# Returns undef if not found. -sub SourceLine { - my $file = shift; - my $line = shift; - - # Look in cache - if (!defined($main::source_cache{$file})) { - if (100 < scalar keys(%main::source_cache)) { - # Clear the cache when it gets too big - $main::source_cache = (); - } - - # Read all lines from the file - if (!open(FILE, "<$file")) { - print STDERR "$file: $!\n"; - $main::source_cache{$file} = []; # Cache the negative result - return undef; - } - my $lines = []; - push(@{$lines}, ""); # So we can use 1-based line numbers as indices - while (<FILE>) { - push(@{$lines}, $_); - } - close(FILE); - - # Save the lines in the cache - $main::source_cache{$file} = $lines; - } - - my $lines = $main::source_cache{$file}; - if (($line < 0) || ($line > $#{$lines})) { - return undef; - } else { - return $lines->[$line]; - } -} - -# Print disassembly for one routine with interspersed source if available -sub PrintDisassembledFunction { - my $prog = shift; - my $offset = shift; - my $routine = shift; - my $flat = shift; - my $cumulative = shift; - my $start_addr = shift; - my $end_addr = shift; - my $total = shift; - - # Disassemble all instructions - my @instructions = Disassemble($prog, $offset, $start_addr, $end_addr); - - # Make array of counts per instruction - my @flat_count = (); - my @cum_count = (); - my $flat_total = 0; - my $cum_total = 0; - foreach my $e (@instructions) { - # Add up counts for all address that fall inside this instruction - my $c1 = 0; - my $c2 = 0; - for (my $a = $e->[0]; $a lt $e->[4]; $a = AddressInc($a)) { - $c1 += GetEntry($flat, $a); - $c2 += GetEntry($cumulative, $a); - } - push(@flat_count, $c1); - push(@cum_count, $c2); - $flat_total += $c1; - $cum_total += $c2; - } - - # Print header with total counts - printf("ROUTINE ====================== %s\n" . - "%6s %6s %s (flat, cumulative) %.1f%% of total\n", - ShortFunctionName($routine), - Unparse($flat_total), - Unparse($cum_total), - Units(), - ($cum_total * 100.0) / $total); - - # Process instructions in order - my $current_file = ""; - for (my $i = 0; $i <= $#instructions; ) { - my $e = $instructions[$i]; - - # Print the new file name whenever we switch files - if ($e->[1] ne $current_file) { - $current_file = $e->[1]; - my $fname = $current_file; - $fname =~ s|^\./||; # Trim leading "./" - - # Shorten long file names - if (length($fname) >= 58) { - $fname = "..." . substr($fname, -55); - } - printf("-------------------- %s\n", $fname); - } - - # TODO: Compute range of lines to print together to deal with - # small reorderings. - my $first_line = $e->[2]; - my $last_line = $first_line; - my %flat_sum = (); - my %cum_sum = (); - for (my $l = $first_line; $l <= $last_line; $l++) { - $flat_sum{$l} = 0; - $cum_sum{$l} = 0; - } - - # Find run of instructions for this range of source lines - my $first_inst = $i; - while (($i <= $#instructions) && - ($instructions[$i]->[2] >= $first_line) && - ($instructions[$i]->[2] <= $last_line)) { - $e = $instructions[$i]; - $flat_sum{$e->[2]} += $flat_count[$i]; - $cum_sum{$e->[2]} += $cum_count[$i]; - $i++; - } - my $last_inst = $i - 1; - - # Print source lines - for (my $l = $first_line; $l <= $last_line; $l++) { - my $line = SourceLine($current_file, $l); - if (!defined($line)) { - $line = "?\n"; - next; - } else { - $line =~ s/^\s+//; - } - printf("%6s %6s %5d: %s", - UnparseAlt($flat_sum{$l}), - UnparseAlt($cum_sum{$l}), - $l, - $line); - } - - # Print disassembly - for (my $x = $first_inst; $x <= $last_inst; $x++) { - my $e = $instructions[$x]; - printf("%6s %6s %8s: %6s\n", - UnparseAlt($flat_count[$x]), - UnparseAlt($cum_count[$x]), - UnparseAddress($offset, $e->[0]), - CleanDisassembly($e->[3])); - } - } -} - -# Print DOT graph -sub PrintDot { - my $prog = shift; - my $symbols = shift; - my $raw = shift; - my $flat = shift; - my $cumulative = shift; - my $overall_total = shift; - - # Get total - my $local_total = TotalProfile($flat); - my $nodelimit = int($main::opt_nodefraction * $local_total); - my $edgelimit = int($main::opt_edgefraction * $local_total); - my $nodecount = $main::opt_nodecount; - - # Find nodes to include - my @list = (sort { abs(GetEntry($cumulative, $b)) <=> - abs(GetEntry($cumulative, $a)) - || $a cmp $b } - keys(%{$cumulative})); - my $last = $nodecount - 1; - if ($last > $#list) { - $last = $#list; - } - while (($last >= 0) && - (abs(GetEntry($cumulative, $list[$last])) <= $nodelimit)) { - $last--; - } - if ($last < 0) { - print STDERR "No nodes to print\n"; - return 0; - } - - if ($nodelimit > 0 || $edgelimit > 0) { - printf STDERR ("Dropping nodes with <= %s %s; edges with <= %s abs(%s)\n", - Unparse($nodelimit), Units(), - Unparse($edgelimit), Units()); - } - - # Open DOT output file - my $output; - my $escaped_dot = ShellEscape(@DOT); - my $escaped_ps2pdf = ShellEscape(@PS2PDF); - if ($main::opt_gv) { - my $escaped_outfile = ShellEscape(TempName($main::next_tmpfile, "ps")); - $output = "| $escaped_dot -Tps2 >$escaped_outfile"; - } elsif ($main::opt_evince) { - my $escaped_outfile = ShellEscape(TempName($main::next_tmpfile, "pdf")); - $output = "| $escaped_dot -Tps2 | $escaped_ps2pdf - $escaped_outfile"; - } elsif ($main::opt_ps) { - $output = "| $escaped_dot -Tps2"; - } elsif ($main::opt_pdf) { - $output = "| $escaped_dot -Tps2 | $escaped_ps2pdf - -"; - } elsif ($main::opt_web || $main::opt_svg) { - # We need to post-process the SVG, so write to a temporary file always. - my $escaped_outfile = ShellEscape(TempName($main::next_tmpfile, "svg")); - $output = "| $escaped_dot -Tsvg >$escaped_outfile"; - } elsif ($main::opt_gif) { - $output = "| $escaped_dot -Tgif"; - } else { - $output = ">&STDOUT"; - } - open(DOT, $output) || error("$output: $!\n"); - - # Title - printf DOT ("digraph \"%s; %s %s\" {\n", - $prog, - Unparse($overall_total), - Units()); - if ($main::opt_pdf) { - # The output is more printable if we set the page size for dot. - printf DOT ("size=\"8,11\"\n"); - } - printf DOT ("node [width=0.375,height=0.25];\n"); - - # Print legend - printf DOT ("Legend [shape=box,fontsize=24,shape=plaintext," . - "label=\"%s\\l%s\\l%s\\l%s\\l%s\\l\"];\n", - $prog, - sprintf("Total %s: %s", Units(), Unparse($overall_total)), - sprintf("Focusing on: %s", Unparse($local_total)), - sprintf("Dropped nodes with <= %s abs(%s)", - Unparse($nodelimit), Units()), - sprintf("Dropped edges with <= %s %s", - Unparse($edgelimit), Units()) - ); - - # Print nodes - my %node = (); - my $nextnode = 1; - foreach my $a (@list[0..$last]) { - # Pick font size - my $f = GetEntry($flat, $a); - my $c = GetEntry($cumulative, $a); - - my $fs = 8; - if ($local_total > 0) { - $fs = 8 + (50.0 * sqrt(abs($f * 1.0 / $local_total))); - } - - $node{$a} = $nextnode++; - my $sym = $a; - $sym =~ s/\s+/\\n/g; - $sym =~ s/::/\\n/g; - - # Extra cumulative info to print for non-leaves - my $extra = ""; - if ($f != $c) { - $extra = sprintf("\\rof %s (%s)", - Unparse($c), - Percent($c, $local_total)); - } - my $style = ""; - if ($main::opt_heapcheck) { - if ($f > 0) { - # make leak-causing nodes more visible (add a background) - $style = ",style=filled,fillcolor=gray" - } elsif ($f < 0) { - # make anti-leak-causing nodes (which almost never occur) - # stand out as well (triple border) - $style = ",peripheries=3" - } - } - - printf DOT ("N%d [label=\"%s\\n%s (%s)%s\\r" . - "\",shape=box,fontsize=%.1f%s];\n", - $node{$a}, - $sym, - Unparse($f), - Percent($f, $local_total), - $extra, - $fs, - $style, - ); - } - - # Get edges and counts per edge - my %edge = (); - my $n; - my $fullname_to_shortname_map = {}; - FillFullnameToShortnameMap($symbols, $fullname_to_shortname_map); - foreach my $k (keys(%{$raw})) { - # TODO: omit low %age edges - $n = $raw->{$k}; - my @translated = TranslateStack($symbols, $fullname_to_shortname_map, $k); - for (my $i = 1; $i <= $#translated; $i++) { - my $src = $translated[$i]; - my $dst = $translated[$i-1]; - #next if ($src eq $dst); # Avoid self-edges? - if (exists($node{$src}) && exists($node{$dst})) { - my $edge_label = "$src\001$dst"; - if (!exists($edge{$edge_label})) { - $edge{$edge_label} = 0; - } - $edge{$edge_label} += $n; - } - } - } - - # Print edges (process in order of decreasing counts) - my %indegree = (); # Number of incoming edges added per node so far - my %outdegree = (); # Number of outgoing edges added per node so far - foreach my $e (sort { $edge{$b} <=> $edge{$a} } keys(%edge)) { - my @x = split(/\001/, $e); - $n = $edge{$e}; - - # Initialize degree of kept incoming and outgoing edges if necessary - my $src = $x[0]; - my $dst = $x[1]; - if (!exists($outdegree{$src})) { $outdegree{$src} = 0; } - if (!exists($indegree{$dst})) { $indegree{$dst} = 0; } - - my $keep; - if ($indegree{$dst} == 0) { - # Keep edge if needed for reachability - $keep = 1; - } elsif (abs($n) <= $edgelimit) { - # Drop if we are below --edgefraction - $keep = 0; - } elsif ($outdegree{$src} >= $main::opt_maxdegree || - $indegree{$dst} >= $main::opt_maxdegree) { - # Keep limited number of in/out edges per node - $keep = 0; - } else { - $keep = 1; - } - - if ($keep) { - $outdegree{$src}++; - $indegree{$dst}++; - - # Compute line width based on edge count - my $fraction = abs($local_total ? (3 * ($n / $local_total)) : 0); - if ($fraction > 1) { $fraction = 1; } - my $w = $fraction * 2; - if ($w < 1 && ($main::opt_web || $main::opt_svg)) { - # SVG output treats line widths < 1 poorly. - $w = 1; - } - - # Dot sometimes segfaults if given edge weights that are too large, so - # we cap the weights at a large value - my $edgeweight = abs($n) ** 0.7; - if ($edgeweight > 100000) { $edgeweight = 100000; } - $edgeweight = int($edgeweight); - - my $style = sprintf("setlinewidth(%f)", $w); - if ($x[1] =~ m/\(inline\)/) { - $style .= ",dashed"; - } - - # Use a slightly squashed function of the edge count as the weight - printf DOT ("N%s -> N%s [label=%s, weight=%d, style=\"%s\"];\n", - $node{$x[0]}, - $node{$x[1]}, - Unparse($n), - $edgeweight, - $style); - } - } - - print DOT ("}\n"); - close(DOT); - - if ($main::opt_web || $main::opt_svg) { - # Rewrite SVG to be more usable inside web browser. - RewriteSvg(TempName($main::next_tmpfile, "svg")); - } - - return 1; -} - -sub RewriteSvg { - my $svgfile = shift; - - open(SVG, $svgfile) || die "open temp svg: $!"; - my @svg = <SVG>; - close(SVG); - unlink $svgfile; - my $svg = join('', @svg); - - # Dot's SVG output is - # - # <svg width="___" height="___" - # viewBox="___" xmlns=...> - # <g id="graph0" transform="..."> - # ... - # </g> - # </svg> - # - # Change it to - # - # <svg width="100%" height="100%" - # xmlns=...> - # $svg_javascript - # <g id="viewport" transform="translate(0,0)"> - # <g id="graph0" transform="..."> - # ... - # </g> - # </g> - # </svg> - - # Fix width, height; drop viewBox. - $svg =~ s/(?s)<svg width="[^"]+" height="[^"]+"(.*?)viewBox="[^"]+"/<svg width="100%" height="100%"$1/; - - # Insert script, viewport <g> above first <g> - my $svg_javascript = SvgJavascript(); - my $viewport = "<g id=\"viewport\" transform=\"translate(0,0)\">\n"; - $svg =~ s/<g id="graph\d"/$svg_javascript$viewport$&/; - - # Insert final </g> above </svg>. - $svg =~ s/(.*)(<\/svg>)/$1<\/g>$2/; - $svg =~ s/<g id="graph\d"(.*?)/<g id="viewport"$1/; - - if ($main::opt_svg) { - # --svg: write to standard output. - print $svg; - } else { - # Write back to temporary file. - open(SVG, ">$svgfile") || die "open $svgfile: $!"; - print SVG $svg; - close(SVG); - } -} - -sub SvgJavascript { - return <<'EOF'; -<script type="text/ecmascript"><![CDATA[ -// SVGPan -// http://www.cyberz.org/blog/2009/12/08/svgpan-a-javascript-svg-panzoomdrag-library/ -// Local modification: if(true || ...) below to force panning, never moving. - -/** - * SVGPan library 1.2 - * ==================== - * - * Given an unique existing element with id "viewport", including the - * the library into any SVG adds the following capabilities: - * - * - Mouse panning - * - Mouse zooming (using the wheel) - * - Object dargging - * - * Known issues: - * - * - Zooming (while panning) on Safari has still some issues - * - * Releases: - * - * 1.2, Sat Mar 20 08:42:50 GMT 2010, Zeng Xiaohui - * Fixed a bug with browser mouse handler interaction - * - * 1.1, Wed Feb 3 17:39:33 GMT 2010, Zeng Xiaohui - * Updated the zoom code to support the mouse wheel on Safari/Chrome - * - * 1.0, Andrea Leofreddi - * First release - * - * This code is licensed under the following BSD license: - * - * Copyright 2009-2010 Andrea Leofreddi <a.leofreddi@itcharm.com>. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY Andrea Leofreddi ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Andrea Leofreddi OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of Andrea Leofreddi. - */ - -var root = document.documentElement; - -var state = 'none', stateTarget, stateOrigin, stateTf; - -setupHandlers(root); - -/** - * Register handlers - */ -function setupHandlers(root){ - setAttributes(root, { - "onmouseup" : "add(evt)", - "onmousedown" : "handleMouseDown(evt)", - "onmousemove" : "handleMouseMove(evt)", - "onmouseup" : "handleMouseUp(evt)", - //"onmouseout" : "handleMouseUp(evt)", // Decomment this to stop the pan functionality when dragging out of the SVG element - }); - - if(navigator.userAgent.toLowerCase().indexOf('webkit') >= 0) - window.addEventListener('mousewheel', handleMouseWheel, false); // Chrome/Safari - else - window.addEventListener('DOMMouseScroll', handleMouseWheel, false); // Others - - var g = svgDoc.getElementById("svg"); - g.width = "100%"; - g.height = "100%"; -} - -/** - * Instance an SVGPoint object with given event coordinates. - */ -function getEventPoint(evt) { - var p = root.createSVGPoint(); - - p.x = evt.clientX; - p.y = evt.clientY; - - return p; -} - -/** - * Sets the current transform matrix of an element. - */ -function setCTM(element, matrix) { - var s = "matrix(" + matrix.a + "," + matrix.b + "," + matrix.c + "," + matrix.d + "," + matrix.e + "," + matrix.f + ")"; - - element.setAttribute("transform", s); -} - -/** - * Dumps a matrix to a string (useful for debug). - */ -function dumpMatrix(matrix) { - var s = "[ " + matrix.a + ", " + matrix.c + ", " + matrix.e + "\n " + matrix.b + ", " + matrix.d + ", " + matrix.f + "\n 0, 0, 1 ]"; - - return s; -} - -/** - * Sets attributes of an element. - */ -function setAttributes(element, attributes){ - for (i in attributes) - element.setAttributeNS(null, i, attributes[i]); -} - -/** - * Handle mouse move event. - */ -function handleMouseWheel(evt) { - if(evt.preventDefault) - evt.preventDefault(); - - evt.returnValue = false; - - var svgDoc = evt.target.ownerDocument; - - var delta; - - if(evt.wheelDelta) - delta = evt.wheelDelta / 3600; // Chrome/Safari - else - delta = evt.detail / -90; // Mozilla - - var z = 1 + delta; // Zoom factor: 0.9/1.1 - - var g = svgDoc.getElementById("viewport"); - - var p = getEventPoint(evt); - - p = p.matrixTransform(g.getCTM().inverse()); - - // Compute new scale matrix in current mouse position - var k = root.createSVGMatrix().translate(p.x, p.y).scale(z).translate(-p.x, -p.y); - - setCTM(g, g.getCTM().multiply(k)); - - stateTf = stateTf.multiply(k.inverse()); -} - -/** - * Handle mouse move event. - */ -function handleMouseMove(evt) { - if(evt.preventDefault) - evt.preventDefault(); - - evt.returnValue = false; - - var svgDoc = evt.target.ownerDocument; - - var g = svgDoc.getElementById("viewport"); - - if(state == 'pan') { - // Pan mode - var p = getEventPoint(evt).matrixTransform(stateTf); - - setCTM(g, stateTf.inverse().translate(p.x - stateOrigin.x, p.y - stateOrigin.y)); - } else if(state == 'move') { - // Move mode - var p = getEventPoint(evt).matrixTransform(g.getCTM().inverse()); - - setCTM(stateTarget, root.createSVGMatrix().translate(p.x - stateOrigin.x, p.y - stateOrigin.y).multiply(g.getCTM().inverse()).multiply(stateTarget.getCTM())); - - stateOrigin = p; - } -} - -/** - * Handle click event. - */ -function handleMouseDown(evt) { - if(evt.preventDefault) - evt.preventDefault(); - - evt.returnValue = false; - - var svgDoc = evt.target.ownerDocument; - - var g = svgDoc.getElementById("viewport"); - - if(true || evt.target.tagName == "svg") { - // Pan mode - state = 'pan'; - - stateTf = g.getCTM().inverse(); - - stateOrigin = getEventPoint(evt).matrixTransform(stateTf); - } else { - // Move mode - state = 'move'; - - stateTarget = evt.target; - - stateTf = g.getCTM().inverse(); - - stateOrigin = getEventPoint(evt).matrixTransform(stateTf); - } -} - -/** - * Handle mouse button release event. - */ -function handleMouseUp(evt) { - if(evt.preventDefault) - evt.preventDefault(); - - evt.returnValue = false; - - var svgDoc = evt.target.ownerDocument; - - if(state == 'pan' || state == 'move') { - // Quit pan mode - state = ''; - } -} - -]]></script> -EOF -} - -# Provides a map from fullname to shortname for cases where the -# shortname is ambiguous. The symlist has both the fullname and -# shortname for all symbols, which is usually fine, but sometimes -- -# such as overloaded functions -- two different fullnames can map to -# the same shortname. In that case, we use the address of the -# function to disambiguate the two. This function fills in a map that -# maps fullnames to modified shortnames in such cases. If a fullname -# is not present in the map, the 'normal' shortname provided by the -# symlist is the appropriate one to use. -sub FillFullnameToShortnameMap { - my $symbols = shift; - my $fullname_to_shortname_map = shift; - my $shortnames_seen_once = {}; - my $shortnames_seen_more_than_once = {}; - - foreach my $symlist (values(%{$symbols})) { - # TODO(csilvers): deal with inlined symbols too. - my $shortname = $symlist->[0]; - my $fullname = $symlist->[2]; - if ($fullname !~ /<[0-9a-fA-F]+>$/) { # fullname doesn't end in an address - next; # the only collisions we care about are when addresses differ - } - if (defined($shortnames_seen_once->{$shortname}) && - $shortnames_seen_once->{$shortname} ne $fullname) { - $shortnames_seen_more_than_once->{$shortname} = 1; - } else { - $shortnames_seen_once->{$shortname} = $fullname; - } - } - - foreach my $symlist (values(%{$symbols})) { - my $shortname = $symlist->[0]; - my $fullname = $symlist->[2]; - # TODO(csilvers): take in a list of addresses we care about, and only - # store in the map if $symlist->[1] is in that list. Saves space. - next if defined($fullname_to_shortname_map->{$fullname}); - if (defined($shortnames_seen_more_than_once->{$shortname})) { - if ($fullname =~ /<0*([^>]*)>$/) { # fullname has address at end of it - $fullname_to_shortname_map->{$fullname} = "$shortname\@$1"; - } - } - } -} - -# Return a small number that identifies the argument. -# Multiple calls with the same argument will return the same number. -# Calls with different arguments will return different numbers. -sub ShortIdFor { - my $key = shift; - my $id = $main::uniqueid{$key}; - if (!defined($id)) { - $id = keys(%main::uniqueid) + 1; - $main::uniqueid{$key} = $id; - } - return $id; -} - -# Translate a stack of addresses into a stack of symbols -sub TranslateStack { - my $symbols = shift; - my $fullname_to_shortname_map = shift; - my $k = shift; - - my @addrs = split(/\n/, $k); - my @result = (); - for (my $i = 0; $i <= $#addrs; $i++) { - my $a = $addrs[$i]; - - # Skip large addresses since they sometimes show up as fake entries on RH9 - if (length($a) > 8 && $a gt "7fffffffffffffff") { - next; - } - - if ($main::opt_disasm || $main::opt_list) { - # We want just the address for the key - push(@result, $a); - next; - } - - my $symlist = $symbols->{$a}; - if (!defined($symlist)) { - $symlist = [$a, "", $a]; - } - - # We can have a sequence of symbols for a particular entry - # (more than one symbol in the case of inlining). Callers - # come before callees in symlist, so walk backwards since - # the translated stack should contain callees before callers. - for (my $j = $#{$symlist}; $j >= 2; $j -= 3) { - my $func = $symlist->[$j-2]; - my $fileline = $symlist->[$j-1]; - my $fullfunc = $symlist->[$j]; - if (defined($fullname_to_shortname_map->{$fullfunc})) { - $func = $fullname_to_shortname_map->{$fullfunc}; - } - if ($j > 2) { - $func = "$func (inline)"; - } - - # Do not merge nodes corresponding to Callback::Run since that - # causes confusing cycles in dot display. Instead, we synthesize - # a unique name for this frame per caller. - if ($func =~ m/Callback.*::Run$/) { - my $caller = ($i > 0) ? $addrs[$i-1] : 0; - $func = "Run#" . ShortIdFor($caller); - } - - if ($main::opt_addresses) { - push(@result, "$a $func $fileline"); - } elsif ($main::opt_lines) { - if ($func eq '??' && $fileline eq '??:0') { - push(@result, "$a"); - } else { - push(@result, "$func $fileline"); - } - } elsif ($main::opt_functions) { - if ($func eq '??') { - push(@result, "$a"); - } else { - push(@result, $func); - } - } elsif ($main::opt_files) { - if ($fileline eq '??:0' || $fileline eq '') { - push(@result, "$a"); - } else { - my $f = $fileline; - $f =~ s/:\d+$//; - push(@result, $f); - } - } else { - push(@result, $a); - last; # Do not print inlined info - } - } - } - - # print join(",", @addrs), " => ", join(",", @result), "\n"; - return @result; -} - -# Generate percent string for a number and a total -sub Percent { - my $num = shift; - my $tot = shift; - if ($tot != 0) { - return sprintf("%.1f%%", $num * 100.0 / $tot); - } else { - return ($num == 0) ? "nan" : (($num > 0) ? "+inf" : "-inf"); - } -} - -# Generate pretty-printed form of number -sub Unparse { - my $num = shift; - if ($main::profile_type eq 'heap' || $main::profile_type eq 'growth') { - if ($main::opt_inuse_objects || $main::opt_alloc_objects) { - return sprintf("%d", $num); - } else { - if ($main::opt_show_bytes) { - return sprintf("%d", $num); - } else { - return sprintf("%.1f", $num / 1048576.0); - } - } - } elsif ($main::profile_type eq 'contention' && !$main::opt_contentions) { - return sprintf("%.3f", $num / 1e9); # Convert nanoseconds to seconds - } else { - return sprintf("%d", $num); - } -} - -# Alternate pretty-printed form: 0 maps to "." -sub UnparseAlt { - my $num = shift; - if ($num == 0) { - return "."; - } else { - return Unparse($num); - } -} - -# Alternate pretty-printed form: 0 maps to "" -sub HtmlPrintNumber { - my $num = shift; - if ($num == 0) { - return ""; - } else { - return Unparse($num); - } -} - -# Return output units -sub Units { - if ($main::profile_type eq 'heap' || $main::profile_type eq 'growth') { - if ($main::opt_inuse_objects || $main::opt_alloc_objects) { - return "objects"; - } else { - if ($main::opt_show_bytes) { - return "B"; - } else { - return "MB"; - } - } - } elsif ($main::profile_type eq 'contention' && !$main::opt_contentions) { - return "seconds"; - } else { - return "samples"; - } -} - -##### Profile manipulation code ##### - -# Generate flattened profile: -# If count is charged to stack [a,b,c,d], in generated profile, -# it will be charged to [a] -sub FlatProfile { - my $profile = shift; - my $result = {}; - foreach my $k (keys(%{$profile})) { - my $count = $profile->{$k}; - my @addrs = split(/\n/, $k); - if ($#addrs >= 0) { - AddEntry($result, $addrs[0], $count); - } - } - return $result; -} - -# Generate cumulative profile: -# If count is charged to stack [a,b,c,d], in generated profile, -# it will be charged to [a], [b], [c], [d] -sub CumulativeProfile { - my $profile = shift; - my $result = {}; - foreach my $k (keys(%{$profile})) { - my $count = $profile->{$k}; - my @addrs = split(/\n/, $k); - foreach my $a (@addrs) { - AddEntry($result, $a, $count); - } - } - return $result; -} - -# If the second-youngest PC on the stack is always the same, returns -# that pc. Otherwise, returns undef. -sub IsSecondPcAlwaysTheSame { - my $profile = shift; - - my $second_pc = undef; - foreach my $k (keys(%{$profile})) { - my @addrs = split(/\n/, $k); - if ($#addrs < 1) { - return undef; - } - if (not defined $second_pc) { - $second_pc = $addrs[1]; - } else { - if ($second_pc ne $addrs[1]) { - return undef; - } - } - } - return $second_pc; -} - -sub ExtractSymbolLocation { - my $symbols = shift; - my $address = shift; - # 'addr2line' outputs "??:0" for unknown locations; we do the - # same to be consistent. - my $location = "??:0:unknown"; - if (exists $symbols->{$address}) { - my $file = $symbols->{$address}->[1]; - if ($file eq "?") { - $file = "??:0" - } - $location = $file . ":" . $symbols->{$address}->[0]; - } - return $location; -} - -# Extracts a graph of calls. -sub ExtractCalls { - my $symbols = shift; - my $profile = shift; - - my $calls = {}; - while( my ($stack_trace, $count) = each %$profile ) { - my @address = split(/\n/, $stack_trace); - my $destination = ExtractSymbolLocation($symbols, $address[0]); - AddEntry($calls, $destination, $count); - for (my $i = 1; $i <= $#address; $i++) { - my $source = ExtractSymbolLocation($symbols, $address[$i]); - my $call = "$source -> $destination"; - AddEntry($calls, $call, $count); - $destination = $source; - } - } - - return $calls; -} - -sub FilterFrames { - my $symbols = shift; - my $profile = shift; - - if ($main::opt_retain eq '' && $main::opt_exclude eq '') { - return $profile; - } - - my $result = {}; - foreach my $k (keys(%{$profile})) { - my $count = $profile->{$k}; - my @addrs = split(/\n/, $k); - my @path = (); - foreach my $a (@addrs) { - my $sym; - if (exists($symbols->{$a})) { - $sym = $symbols->{$a}->[0]; - } else { - $sym = $a; - } - if ($main::opt_retain ne '' && $sym !~ m/$main::opt_retain/) { - next; - } - if ($main::opt_exclude ne '' && $sym =~ m/$main::opt_exclude/) { - next; - } - push(@path, $a); - } - if (scalar(@path) > 0) { - my $reduced_path = join("\n", @path); - AddEntry($result, $reduced_path, $count); - } - } - - return $result; -} - -sub RemoveUninterestingFrames { - my $symbols = shift; - my $profile = shift; - - # List of function names to skip - my %skip = (); - my $skip_regexp = 'NOMATCH'; - if ($main::profile_type eq 'heap' || $main::profile_type eq 'growth') { - foreach my $name ('@JEMALLOC_PREFIX@calloc', - 'cfree', - '@JEMALLOC_PREFIX@malloc', - 'newImpl', - 'void* newImpl', - '@JEMALLOC_PREFIX@free', - '@JEMALLOC_PREFIX@memalign', - '@JEMALLOC_PREFIX@posix_memalign', - '@JEMALLOC_PREFIX@aligned_alloc', - 'pvalloc', - '@JEMALLOC_PREFIX@valloc', - '@JEMALLOC_PREFIX@realloc', - '@JEMALLOC_PREFIX@mallocx', - '@JEMALLOC_PREFIX@rallocx', - '@JEMALLOC_PREFIX@xallocx', - '@JEMALLOC_PREFIX@dallocx', - '@JEMALLOC_PREFIX@sdallocx', - '@JEMALLOC_PREFIX@sdallocx_noflags', - 'tc_calloc', - 'tc_cfree', - 'tc_malloc', - 'tc_free', - 'tc_memalign', - 'tc_posix_memalign', - 'tc_pvalloc', - 'tc_valloc', - 'tc_realloc', - 'tc_new', - 'tc_delete', - 'tc_newarray', - 'tc_deletearray', - 'tc_new_nothrow', - 'tc_newarray_nothrow', - 'do_malloc', - '::do_malloc', # new name -- got moved to an unnamed ns - '::do_malloc_or_cpp_alloc', - 'DoSampledAllocation', - 'simple_alloc::allocate', - '__malloc_alloc_template::allocate', - '__builtin_delete', - '__builtin_new', - '__builtin_vec_delete', - '__builtin_vec_new', - 'operator new', - 'operator new[]', - # The entry to our memory-allocation routines on OS X - 'malloc_zone_malloc', - 'malloc_zone_calloc', - 'malloc_zone_valloc', - 'malloc_zone_realloc', - 'malloc_zone_memalign', - 'malloc_zone_free', - # These mark the beginning/end of our custom sections - '__start_google_malloc', - '__stop_google_malloc', - '__start_malloc_hook', - '__stop_malloc_hook') { - $skip{$name} = 1; - $skip{"_" . $name} = 1; # Mach (OS X) adds a _ prefix to everything - } - # TODO: Remove TCMalloc once everything has been - # moved into the tcmalloc:: namespace and we have flushed - # old code out of the system. - $skip_regexp = "TCMalloc|^tcmalloc::"; - } elsif ($main::profile_type eq 'contention') { - foreach my $vname ('base::RecordLockProfileData', - 'base::SubmitMutexProfileData', - 'base::SubmitSpinLockProfileData', - 'Mutex::Unlock', - 'Mutex::UnlockSlow', - 'Mutex::ReaderUnlock', - 'MutexLock::~MutexLock', - 'SpinLock::Unlock', - 'SpinLock::SlowUnlock', - 'SpinLockHolder::~SpinLockHolder') { - $skip{$vname} = 1; - } - } elsif ($main::profile_type eq 'cpu') { - # Drop signal handlers used for CPU profile collection - # TODO(dpeng): this should not be necessary; it's taken - # care of by the general 2nd-pc mechanism below. - foreach my $name ('ProfileData::Add', # historical - 'ProfileData::prof_handler', # historical - 'CpuProfiler::prof_handler', - '__FRAME_END__', - '__pthread_sighandler', - '__restore') { - $skip{$name} = 1; - } - } else { - # Nothing skipped for unknown types - } - - if ($main::profile_type eq 'cpu') { - # If all the second-youngest program counters are the same, - # this STRONGLY suggests that it is an artifact of measurement, - # i.e., stack frames pushed by the CPU profiler signal handler. - # Hence, we delete them. - # (The topmost PC is read from the signal structure, not from - # the stack, so it does not get involved.) - while (my $second_pc = IsSecondPcAlwaysTheSame($profile)) { - my $result = {}; - my $func = ''; - if (exists($symbols->{$second_pc})) { - $second_pc = $symbols->{$second_pc}->[0]; - } - print STDERR "Removing $second_pc from all stack traces.\n"; - foreach my $k (keys(%{$profile})) { - my $count = $profile->{$k}; - my @addrs = split(/\n/, $k); - splice @addrs, 1, 1; - my $reduced_path = join("\n", @addrs); - AddEntry($result, $reduced_path, $count); - } - $profile = $result; - } - } - - my $result = {}; - foreach my $k (keys(%{$profile})) { - my $count = $profile->{$k}; - my @addrs = split(/\n/, $k); - my @path = (); - foreach my $a (@addrs) { - if (exists($symbols->{$a})) { - my $func = $symbols->{$a}->[0]; - if ($skip{$func} || ($func =~ m/$skip_regexp/)) { - # Throw away the portion of the backtrace seen so far, under the - # assumption that previous frames were for functions internal to the - # allocator. - @path = (); - next; - } - } - push(@path, $a); - } - my $reduced_path = join("\n", @path); - AddEntry($result, $reduced_path, $count); - } - - $result = FilterFrames($symbols, $result); - - return $result; -} - -# Reduce profile to granularity given by user -sub ReduceProfile { - my $symbols = shift; - my $profile = shift; - my $result = {}; - my $fullname_to_shortname_map = {}; - FillFullnameToShortnameMap($symbols, $fullname_to_shortname_map); - foreach my $k (keys(%{$profile})) { - my $count = $profile->{$k}; - my @translated = TranslateStack($symbols, $fullname_to_shortname_map, $k); - my @path = (); - my %seen = (); - $seen{''} = 1; # So that empty keys are skipped - foreach my $e (@translated) { - # To avoid double-counting due to recursion, skip a stack-trace - # entry if it has already been seen - if (!$seen{$e}) { - $seen{$e} = 1; - push(@path, $e); - } - } - my $reduced_path = join("\n", @path); - AddEntry($result, $reduced_path, $count); - } - return $result; -} - -# Does the specified symbol array match the regexp? -sub SymbolMatches { - my $sym = shift; - my $re = shift; - if (defined($sym)) { - for (my $i = 0; $i < $#{$sym}; $i += 3) { - if ($sym->[$i] =~ m/$re/ || $sym->[$i+1] =~ m/$re/) { - return 1; - } - } - } - return 0; -} - -# Focus only on paths involving specified regexps -sub FocusProfile { - my $symbols = shift; - my $profile = shift; - my $focus = shift; - my $result = {}; - foreach my $k (keys(%{$profile})) { - my $count = $profile->{$k}; - my @addrs = split(/\n/, $k); - foreach my $a (@addrs) { - # Reply if it matches either the address/shortname/fileline - if (($a =~ m/$focus/) || SymbolMatches($symbols->{$a}, $focus)) { - AddEntry($result, $k, $count); - last; - } - } - } - return $result; -} - -# Focus only on paths not involving specified regexps -sub IgnoreProfile { - my $symbols = shift; - my $profile = shift; - my $ignore = shift; - my $result = {}; - foreach my $k (keys(%{$profile})) { - my $count = $profile->{$k}; - my @addrs = split(/\n/, $k); - my $matched = 0; - foreach my $a (@addrs) { - # Reply if it matches either the address/shortname/fileline - if (($a =~ m/$ignore/) || SymbolMatches($symbols->{$a}, $ignore)) { - $matched = 1; - last; - } - } - if (!$matched) { - AddEntry($result, $k, $count); - } - } - return $result; -} - -# Get total count in profile -sub TotalProfile { - my $profile = shift; - my $result = 0; - foreach my $k (keys(%{$profile})) { - $result += $profile->{$k}; - } - return $result; -} - -# Add A to B -sub AddProfile { - my $A = shift; - my $B = shift; - - my $R = {}; - # add all keys in A - foreach my $k (keys(%{$A})) { - my $v = $A->{$k}; - AddEntry($R, $k, $v); - } - # add all keys in B - foreach my $k (keys(%{$B})) { - my $v = $B->{$k}; - AddEntry($R, $k, $v); - } - return $R; -} - -# Merges symbol maps -sub MergeSymbols { - my $A = shift; - my $B = shift; - - my $R = {}; - foreach my $k (keys(%{$A})) { - $R->{$k} = $A->{$k}; - } - if (defined($B)) { - foreach my $k (keys(%{$B})) { - $R->{$k} = $B->{$k}; - } - } - return $R; -} - - -# Add A to B -sub AddPcs { - my $A = shift; - my $B = shift; - - my $R = {}; - # add all keys in A - foreach my $k (keys(%{$A})) { - $R->{$k} = 1 - } - # add all keys in B - foreach my $k (keys(%{$B})) { - $R->{$k} = 1 - } - return $R; -} - -# Subtract B from A -sub SubtractProfile { - my $A = shift; - my $B = shift; - - my $R = {}; - foreach my $k (keys(%{$A})) { - my $v = $A->{$k} - GetEntry($B, $k); - if ($v < 0 && $main::opt_drop_negative) { - $v = 0; - } - AddEntry($R, $k, $v); - } - if (!$main::opt_drop_negative) { - # Take care of when subtracted profile has more entries - foreach my $k (keys(%{$B})) { - if (!exists($A->{$k})) { - AddEntry($R, $k, 0 - $B->{$k}); - } - } - } - return $R; -} - -# Get entry from profile; zero if not present -sub GetEntry { - my $profile = shift; - my $k = shift; - if (exists($profile->{$k})) { - return $profile->{$k}; - } else { - return 0; - } -} - -# Add entry to specified profile -sub AddEntry { - my $profile = shift; - my $k = shift; - my $n = shift; - if (!exists($profile->{$k})) { - $profile->{$k} = 0; - } - $profile->{$k} += $n; -} - -# Add a stack of entries to specified profile, and add them to the $pcs -# list. -sub AddEntries { - my $profile = shift; - my $pcs = shift; - my $stack = shift; - my $count = shift; - my @k = (); - - foreach my $e (split(/\s+/, $stack)) { - my $pc = HexExtend($e); - $pcs->{$pc} = 1; - push @k, $pc; - } - AddEntry($profile, (join "\n", @k), $count); -} - -##### Code to profile a server dynamically ##### - -sub CheckSymbolPage { - my $url = SymbolPageURL(); - my $command = ShellEscape(@URL_FETCHER, $url); - open(SYMBOL, "$command |") or error($command); - my $line = <SYMBOL>; - $line =~ s/\r//g; # turn windows-looking lines into unix-looking lines - close(SYMBOL); - unless (defined($line)) { - error("$url doesn't exist\n"); - } - - if ($line =~ /^num_symbols:\s+(\d+)$/) { - if ($1 == 0) { - error("Stripped binary. No symbols available.\n"); - } - } else { - error("Failed to get the number of symbols from $url\n"); - } -} - -sub IsProfileURL { - my $profile_name = shift; - if (-f $profile_name) { - printf STDERR "Using local file $profile_name.\n"; - return 0; - } - return 1; -} - -sub ParseProfileURL { - my $profile_name = shift; - - if (!defined($profile_name) || $profile_name eq "") { - return (); - } - - # Split profile URL - matches all non-empty strings, so no test. - $profile_name =~ m,^(https?://)?([^/]+)(.*?)(/|$PROFILES)?$,; - - my $proto = $1 || "http://"; - my $hostport = $2; - my $prefix = $3; - my $profile = $4 || "/"; - - my $host = $hostport; - $host =~ s/:.*//; - - my $baseurl = "$proto$hostport$prefix"; - return ($host, $baseurl, $profile); -} - -# We fetch symbols from the first profile argument. -sub SymbolPageURL { - my ($host, $baseURL, $path) = ParseProfileURL($main::pfile_args[0]); - return "$baseURL$SYMBOL_PAGE"; -} - -sub FetchProgramName() { - my ($host, $baseURL, $path) = ParseProfileURL($main::pfile_args[0]); - my $url = "$baseURL$PROGRAM_NAME_PAGE"; - my $command_line = ShellEscape(@URL_FETCHER, $url); - open(CMDLINE, "$command_line |") or error($command_line); - my $cmdline = <CMDLINE>; - $cmdline =~ s/\r//g; # turn windows-looking lines into unix-looking lines - close(CMDLINE); - error("Failed to get program name from $url\n") unless defined($cmdline); - $cmdline =~ s/\x00.+//; # Remove argv[1] and latters. - $cmdline =~ s!\n!!g; # Remove LFs. - return $cmdline; -} - -# Gee, curl's -L (--location) option isn't reliable at least -# with its 7.12.3 version. Curl will forget to post data if -# there is a redirection. This function is a workaround for -# curl. Redirection happens on borg hosts. -sub ResolveRedirectionForCurl { - my $url = shift; - my $command_line = ShellEscape(@URL_FETCHER, "--head", $url); - open(CMDLINE, "$command_line |") or error($command_line); - while (<CMDLINE>) { - s/\r//g; # turn windows-looking lines into unix-looking lines - if (/^Location: (.*)/) { - $url = $1; - } - } - close(CMDLINE); - return $url; -} - -# Add a timeout flat to URL_FETCHER. Returns a new list. -sub AddFetchTimeout { - my $timeout = shift; - my @fetcher = @_; - if (defined($timeout)) { - if (join(" ", @fetcher) =~ m/\bcurl -s/) { - push(@fetcher, "--max-time", sprintf("%d", $timeout)); - } elsif (join(" ", @fetcher) =~ m/\brpcget\b/) { - push(@fetcher, sprintf("--deadline=%d", $timeout)); - } - } - return @fetcher; -} - -# Reads a symbol map from the file handle name given as $1, returning -# the resulting symbol map. Also processes variables relating to symbols. -# Currently, the only variable processed is 'binary=<value>' which updates -# $main::prog to have the correct program name. -sub ReadSymbols { - my $in = shift; - my $map = {}; - while (<$in>) { - s/\r//g; # turn windows-looking lines into unix-looking lines - # Removes all the leading zeroes from the symbols, see comment below. - if (m/^0x0*([0-9a-f]+)\s+(.+)/) { - $map->{$1} = $2; - } elsif (m/^---/) { - last; - } elsif (m/^([a-z][^=]*)=(.*)$/ ) { - my ($variable, $value) = ($1, $2); - for ($variable, $value) { - s/^\s+//; - s/\s+$//; - } - if ($variable eq "binary") { - if ($main::prog ne $UNKNOWN_BINARY && $main::prog ne $value) { - printf STDERR ("Warning: Mismatched binary name '%s', using '%s'.\n", - $main::prog, $value); - } - $main::prog = $value; - } else { - printf STDERR ("Ignoring unknown variable in symbols list: " . - "'%s' = '%s'\n", $variable, $value); - } - } - } - return $map; -} - -sub URLEncode { - my $str = shift; - $str =~ s/([^A-Za-z0-9\-_.!~*'()])/ sprintf "%%%02x", ord $1 /eg; - return $str; -} - -sub AppendSymbolFilterParams { - my $url = shift; - my @params = (); - if ($main::opt_retain ne '') { - push(@params, sprintf("retain=%s", URLEncode($main::opt_retain))); - } - if ($main::opt_exclude ne '') { - push(@params, sprintf("exclude=%s", URLEncode($main::opt_exclude))); - } - if (scalar @params > 0) { - $url = sprintf("%s?%s", $url, join("&", @params)); - } - return $url; -} - -# Fetches and processes symbols to prepare them for use in the profile output -# code. If the optional 'symbol_map' arg is not given, fetches symbols from -# $SYMBOL_PAGE for all PC values found in profile. Otherwise, the raw symbols -# are assumed to have already been fetched into 'symbol_map' and are simply -# extracted and processed. -sub FetchSymbols { - my $pcset = shift; - my $symbol_map = shift; - - my %seen = (); - my @pcs = grep { !$seen{$_}++ } keys(%$pcset); # uniq - - if (!defined($symbol_map)) { - my $post_data = join("+", sort((map {"0x" . "$_"} @pcs))); - - open(POSTFILE, ">$main::tmpfile_sym"); - print POSTFILE $post_data; - close(POSTFILE); - - my $url = SymbolPageURL(); - - my $command_line; - if (join(" ", @URL_FETCHER) =~ m/\bcurl -s/) { - $url = ResolveRedirectionForCurl($url); - $url = AppendSymbolFilterParams($url); - $command_line = ShellEscape(@URL_FETCHER, "-d", "\@$main::tmpfile_sym", - $url); - } else { - $url = AppendSymbolFilterParams($url); - $command_line = (ShellEscape(@URL_FETCHER, "--post", $url) - . " < " . ShellEscape($main::tmpfile_sym)); - } - # We use c++filt in case $SYMBOL_PAGE gives us mangled symbols. - my $escaped_cppfilt = ShellEscape($obj_tool_map{"c++filt"}); - open(SYMBOL, "$command_line | $escaped_cppfilt |") or error($command_line); - $symbol_map = ReadSymbols(*SYMBOL{IO}); - close(SYMBOL); - } - - my $symbols = {}; - foreach my $pc (@pcs) { - my $fullname; - # For 64 bits binaries, symbols are extracted with 8 leading zeroes. - # Then /symbol reads the long symbols in as uint64, and outputs - # the result with a "0x%08llx" format which get rid of the zeroes. - # By removing all the leading zeroes in both $pc and the symbols from - # /symbol, the symbols match and are retrievable from the map. - my $shortpc = $pc; - $shortpc =~ s/^0*//; - # Each line may have a list of names, which includes the function - # and also other functions it has inlined. They are separated (in - # PrintSymbolizedProfile), by --, which is illegal in function names. - my $fullnames; - if (defined($symbol_map->{$shortpc})) { - $fullnames = $symbol_map->{$shortpc}; - } else { - $fullnames = "0x" . $pc; # Just use addresses - } - my $sym = []; - $symbols->{$pc} = $sym; - foreach my $fullname (split("--", $fullnames)) { - my $name = ShortFunctionName($fullname); - push(@{$sym}, $name, "?", $fullname); - } - } - return $symbols; -} - -sub BaseName { - my $file_name = shift; - $file_name =~ s!^.*/!!; # Remove directory name - return $file_name; -} - -sub MakeProfileBaseName { - my ($binary_name, $profile_name) = @_; - my ($host, $baseURL, $path) = ParseProfileURL($profile_name); - my $binary_shortname = BaseName($binary_name); - return sprintf("%s.%s.%s", - $binary_shortname, $main::op_time, $host); -} - -sub FetchDynamicProfile { - my $binary_name = shift; - my $profile_name = shift; - my $fetch_name_only = shift; - my $encourage_patience = shift; - - if (!IsProfileURL($profile_name)) { - return $profile_name; - } else { - my ($host, $baseURL, $path) = ParseProfileURL($profile_name); - if ($path eq "" || $path eq "/") { - # Missing type specifier defaults to cpu-profile - $path = $PROFILE_PAGE; - } - - my $profile_file = MakeProfileBaseName($binary_name, $profile_name); - - my $url = "$baseURL$path"; - my $fetch_timeout = undef; - if ($path =~ m/$PROFILE_PAGE|$PMUPROFILE_PAGE/) { - if ($path =~ m/[?]/) { - $url .= "&"; - } else { - $url .= "?"; - } - $url .= sprintf("seconds=%d", $main::opt_seconds); - $fetch_timeout = $main::opt_seconds * 1.01 + 60; - # Set $profile_type for consumption by PrintSymbolizedProfile. - $main::profile_type = 'cpu'; - } else { - # For non-CPU profiles, we add a type-extension to - # the target profile file name. - my $suffix = $path; - $suffix =~ s,/,.,g; - $profile_file .= $suffix; - # Set $profile_type for consumption by PrintSymbolizedProfile. - if ($path =~ m/$HEAP_PAGE/) { - $main::profile_type = 'heap'; - } elsif ($path =~ m/$GROWTH_PAGE/) { - $main::profile_type = 'growth'; - } elsif ($path =~ m/$CONTENTION_PAGE/) { - $main::profile_type = 'contention'; - } - } - - my $profile_dir = $ENV{"JEPROF_TMPDIR"} || ($ENV{HOME} . "/jeprof"); - if (! -d $profile_dir) { - mkdir($profile_dir) - || die("Unable to create profile directory $profile_dir: $!\n"); - } - my $tmp_profile = "$profile_dir/.tmp.$profile_file"; - my $real_profile = "$profile_dir/$profile_file"; - - if ($fetch_name_only > 0) { - return $real_profile; - } - - my @fetcher = AddFetchTimeout($fetch_timeout, @URL_FETCHER); - my $cmd = ShellEscape(@fetcher, $url) . " > " . ShellEscape($tmp_profile); - if ($path =~ m/$PROFILE_PAGE|$PMUPROFILE_PAGE|$CENSUSPROFILE_PAGE/){ - print STDERR "Gathering CPU profile from $url for $main::opt_seconds seconds to\n ${real_profile}\n"; - if ($encourage_patience) { - print STDERR "Be patient...\n"; - } - } else { - print STDERR "Fetching $path profile from $url to\n ${real_profile}\n"; - } - - (system($cmd) == 0) || error("Failed to get profile: $cmd: $!\n"); - (system("mv", $tmp_profile, $real_profile) == 0) || error("Unable to rename profile\n"); - print STDERR "Wrote profile to $real_profile\n"; - $main::collected_profile = $real_profile; - return $main::collected_profile; - } -} - -# Collect profiles in parallel -sub FetchDynamicProfiles { - my $items = scalar(@main::pfile_args); - my $levels = log($items) / log(2); - - if ($items == 1) { - $main::profile_files[0] = FetchDynamicProfile($main::prog, $main::pfile_args[0], 0, 1); - } else { - # math rounding issues - if ((2 ** $levels) < $items) { - $levels++; - } - my $count = scalar(@main::pfile_args); - for (my $i = 0; $i < $count; $i++) { - $main::profile_files[$i] = FetchDynamicProfile($main::prog, $main::pfile_args[$i], 1, 0); - } - print STDERR "Fetching $count profiles, Be patient...\n"; - FetchDynamicProfilesRecurse($levels, 0, 0); - $main::collected_profile = join(" \\\n ", @main::profile_files); - } -} - -# Recursively fork a process to get enough processes -# collecting profiles -sub FetchDynamicProfilesRecurse { - my $maxlevel = shift; - my $level = shift; - my $position = shift; - - if (my $pid = fork()) { - $position = 0 | ($position << 1); - TryCollectProfile($maxlevel, $level, $position); - wait; - } else { - $position = 1 | ($position << 1); - TryCollectProfile($maxlevel, $level, $position); - cleanup(); - exit(0); - } -} - -# Collect a single profile -sub TryCollectProfile { - my $maxlevel = shift; - my $level = shift; - my $position = shift; - - if ($level >= ($maxlevel - 1)) { - if ($position < scalar(@main::pfile_args)) { - FetchDynamicProfile($main::prog, $main::pfile_args[$position], 0, 0); - } - } else { - FetchDynamicProfilesRecurse($maxlevel, $level+1, $position); - } -} - -##### Parsing code ##### - -# Provide a small streaming-read module to handle very large -# cpu-profile files. Stream in chunks along a sliding window. -# Provides an interface to get one 'slot', correctly handling -# endian-ness differences. A slot is one 32-bit or 64-bit word -# (depending on the input profile). We tell endianness and bit-size -# for the profile by looking at the first 8 bytes: in cpu profiles, -# the second slot is always 3 (we'll accept anything that's not 0). -BEGIN { - package CpuProfileStream; - - sub new { - my ($class, $file, $fname) = @_; - my $self = { file => $file, - base => 0, - stride => 512 * 1024, # must be a multiple of bitsize/8 - slots => [], - unpack_code => "", # N for big-endian, V for little - perl_is_64bit => 1, # matters if profile is 64-bit - }; - bless $self, $class; - # Let unittests adjust the stride - if ($main::opt_test_stride > 0) { - $self->{stride} = $main::opt_test_stride; - } - # Read the first two slots to figure out bitsize and endianness. - my $slots = $self->{slots}; - my $str; - read($self->{file}, $str, 8); - # Set the global $address_length based on what we see here. - # 8 is 32-bit (8 hexadecimal chars); 16 is 64-bit (16 hexadecimal chars). - $address_length = ($str eq (chr(0)x8)) ? 16 : 8; - if ($address_length == 8) { - if (substr($str, 6, 2) eq chr(0)x2) { - $self->{unpack_code} = 'V'; # Little-endian. - } elsif (substr($str, 4, 2) eq chr(0)x2) { - $self->{unpack_code} = 'N'; # Big-endian - } else { - ::error("$fname: header size >= 2**16\n"); - } - @$slots = unpack($self->{unpack_code} . "*", $str); - } else { - # If we're a 64-bit profile, check if we're a 64-bit-capable - # perl. Otherwise, each slot will be represented as a float - # instead of an int64, losing precision and making all the - # 64-bit addresses wrong. We won't complain yet, but will - # later if we ever see a value that doesn't fit in 32 bits. - my $has_q = 0; - eval { $has_q = pack("Q", "1") ? 1 : 1; }; - if (!$has_q) { - $self->{perl_is_64bit} = 0; - } - read($self->{file}, $str, 8); - if (substr($str, 4, 4) eq chr(0)x4) { - # We'd love to use 'Q', but it's a) not universal, b) not endian-proof. - $self->{unpack_code} = 'V'; # Little-endian. - } elsif (substr($str, 0, 4) eq chr(0)x4) { - $self->{unpack_code} = 'N'; # Big-endian - } else { - ::error("$fname: header size >= 2**32\n"); - } - my @pair = unpack($self->{unpack_code} . "*", $str); - # Since we know one of the pair is 0, it's fine to just add them. - @$slots = (0, $pair[0] + $pair[1]); - } - return $self; - } - - # Load more data when we access slots->get(X) which is not yet in memory. - sub overflow { - my ($self) = @_; - my $slots = $self->{slots}; - $self->{base} += $#$slots + 1; # skip over data we're replacing - my $str; - read($self->{file}, $str, $self->{stride}); - if ($address_length == 8) { # the 32-bit case - # This is the easy case: unpack provides 32-bit unpacking primitives. - @$slots = unpack($self->{unpack_code} . "*", $str); - } else { - # We need to unpack 32 bits at a time and combine. - my @b32_values = unpack($self->{unpack_code} . "*", $str); - my @b64_values = (); - for (my $i = 0; $i < $#b32_values; $i += 2) { - # TODO(csilvers): if this is a 32-bit perl, the math below - # could end up in a too-large int, which perl will promote - # to a double, losing necessary precision. Deal with that. - # Right now, we just die. - my ($lo, $hi) = ($b32_values[$i], $b32_values[$i+1]); - if ($self->{unpack_code} eq 'N') { # big-endian - ($lo, $hi) = ($hi, $lo); - } - my $value = $lo + $hi * (2**32); - if (!$self->{perl_is_64bit} && # check value is exactly represented - (($value % (2**32)) != $lo || int($value / (2**32)) != $hi)) { - ::error("Need a 64-bit perl to process this 64-bit profile.\n"); - } - push(@b64_values, $value); - } - @$slots = @b64_values; - } - } - - # Access the i-th long in the file (logically), or -1 at EOF. - sub get { - my ($self, $idx) = @_; - my $slots = $self->{slots}; - while ($#$slots >= 0) { - if ($idx < $self->{base}) { - # The only time we expect a reference to $slots[$i - something] - # after referencing $slots[$i] is reading the very first header. - # Since $stride > |header|, that shouldn't cause any lookback - # errors. And everything after the header is sequential. - print STDERR "Unexpected look-back reading CPU profile"; - return -1; # shrug, don't know what better to return - } elsif ($idx > $self->{base} + $#$slots) { - $self->overflow(); - } else { - return $slots->[$idx - $self->{base}]; - } - } - # If we get here, $slots is [], which means we've reached EOF - return -1; # unique since slots is supposed to hold unsigned numbers - } -} - -# Reads the top, 'header' section of a profile, and returns the last -# line of the header, commonly called a 'header line'. The header -# section of a profile consists of zero or more 'command' lines that -# are instructions to jeprof, which jeprof executes when reading the -# header. All 'command' lines start with a %. After the command -# lines is the 'header line', which is a profile-specific line that -# indicates what type of profile it is, and perhaps other global -# information about the profile. For instance, here's a header line -# for a heap profile: -# heap profile: 53: 38236 [ 5525: 1284029] @ heapprofile -# For historical reasons, the CPU profile does not contain a text- -# readable header line. If the profile looks like a CPU profile, -# this function returns "". If no header line could be found, this -# function returns undef. -# -# The following commands are recognized: -# %warn -- emit the rest of this line to stderr, prefixed by 'WARNING:' -# -# The input file should be in binmode. -sub ReadProfileHeader { - local *PROFILE = shift; - my $firstchar = ""; - my $line = ""; - read(PROFILE, $firstchar, 1); - seek(PROFILE, -1, 1); # unread the firstchar - if ($firstchar !~ /[[:print:]]/) { # is not a text character - return ""; - } - while (defined($line = <PROFILE>)) { - $line =~ s/\r//g; # turn windows-looking lines into unix-looking lines - if ($line =~ /^%warn\s+(.*)/) { # 'warn' command - # Note this matches both '%warn blah\n' and '%warn\n'. - print STDERR "WARNING: $1\n"; # print the rest of the line - } elsif ($line =~ /^%/) { - print STDERR "Ignoring unknown command from profile header: $line"; - } else { - # End of commands, must be the header line. - return $line; - } - } - return undef; # got to EOF without seeing a header line -} - -sub IsSymbolizedProfileFile { - my $file_name = shift; - if (!(-e $file_name) || !(-r $file_name)) { - return 0; - } - # Check if the file contains a symbol-section marker. - open(TFILE, "<$file_name"); - binmode TFILE; - my $firstline = ReadProfileHeader(*TFILE); - close(TFILE); - if (!$firstline) { - return 0; - } - $SYMBOL_PAGE =~ m,[^/]+$,; # matches everything after the last slash - my $symbol_marker = $&; - return $firstline =~ /^--- *$symbol_marker/; -} - -# Parse profile generated by common/profiler.cc and return a reference -# to a map: -# $result->{version} Version number of profile file -# $result->{period} Sampling period (in microseconds) -# $result->{profile} Profile object -# $result->{threads} Map of thread IDs to profile objects -# $result->{map} Memory map info from profile -# $result->{pcs} Hash of all PC values seen, key is hex address -sub ReadProfile { - my $prog = shift; - my $fname = shift; - my $result; # return value - - $CONTENTION_PAGE =~ m,[^/]+$,; # matches everything after the last slash - my $contention_marker = $&; - $GROWTH_PAGE =~ m,[^/]+$,; # matches everything after the last slash - my $growth_marker = $&; - $SYMBOL_PAGE =~ m,[^/]+$,; # matches everything after the last slash - my $symbol_marker = $&; - $PROFILE_PAGE =~ m,[^/]+$,; # matches everything after the last slash - my $profile_marker = $&; - $HEAP_PAGE =~ m,[^/]+$,; # matches everything after the last slash - my $heap_marker = $&; - - # Look at first line to see if it is a heap or a CPU profile. - # CPU profile may start with no header at all, and just binary data - # (starting with \0\0\0\0) -- in that case, don't try to read the - # whole firstline, since it may be gigabytes(!) of data. - open(PROFILE, "<$fname") || error("$fname: $!\n"); - binmode PROFILE; # New perls do UTF-8 processing - my $header = ReadProfileHeader(*PROFILE); - if (!defined($header)) { # means "at EOF" - error("Profile is empty.\n"); - } - - my $symbols; - if ($header =~ m/^--- *$symbol_marker/o) { - # Verify that the user asked for a symbolized profile - if (!$main::use_symbolized_profile) { - # we have both a binary and symbolized profiles, abort - error("FATAL ERROR: Symbolized profile\n $fname\ncannot be used with " . - "a binary arg. Try again without passing\n $prog\n"); - } - # Read the symbol section of the symbolized profile file. - $symbols = ReadSymbols(*PROFILE{IO}); - # Read the next line to get the header for the remaining profile. - $header = ReadProfileHeader(*PROFILE) || ""; - } - - if ($header =~ m/^--- *($heap_marker|$growth_marker)/o) { - # Skip "--- ..." line for profile types that have their own headers. - $header = ReadProfileHeader(*PROFILE) || ""; - } - - $main::profile_type = ''; - - if ($header =~ m/^heap profile:.*$growth_marker/o) { - $main::profile_type = 'growth'; - $result = ReadHeapProfile($prog, *PROFILE, $header); - } elsif ($header =~ m/^heap profile:/) { - $main::profile_type = 'heap'; - $result = ReadHeapProfile($prog, *PROFILE, $header); - } elsif ($header =~ m/^heap/) { - $main::profile_type = 'heap'; - $result = ReadThreadedHeapProfile($prog, $fname, $header); - } elsif ($header =~ m/^--- *$contention_marker/o) { - $main::profile_type = 'contention'; - $result = ReadSynchProfile($prog, *PROFILE); - } elsif ($header =~ m/^--- *Stacks:/) { - print STDERR - "Old format contention profile: mistakenly reports " . - "condition variable signals as lock contentions.\n"; - $main::profile_type = 'contention'; - $result = ReadSynchProfile($prog, *PROFILE); - } elsif ($header =~ m/^--- *$profile_marker/) { - # the binary cpu profile data starts immediately after this line - $main::profile_type = 'cpu'; - $result = ReadCPUProfile($prog, $fname, *PROFILE); - } else { - if (defined($symbols)) { - # a symbolized profile contains a format we don't recognize, bail out - error("$fname: Cannot recognize profile section after symbols.\n"); - } - # no ascii header present -- must be a CPU profile - $main::profile_type = 'cpu'; - $result = ReadCPUProfile($prog, $fname, *PROFILE); - } - - close(PROFILE); - - # if we got symbols along with the profile, return those as well - if (defined($symbols)) { - $result->{symbols} = $symbols; - } - - return $result; -} - -# Subtract one from caller pc so we map back to call instr. -# However, don't do this if we're reading a symbolized profile -# file, in which case the subtract-one was done when the file -# was written. -# -# We apply the same logic to all readers, though ReadCPUProfile uses an -# independent implementation. -sub FixCallerAddresses { - my $stack = shift; - # --raw/http: Always subtract one from pc's, because PrintSymbolizedProfile() - # dumps unadjusted profiles. - { - $stack =~ /(\s)/; - my $delimiter = $1; - my @addrs = split(' ', $stack); - my @fixedaddrs; - $#fixedaddrs = $#addrs; - if ($#addrs >= 0) { - $fixedaddrs[0] = $addrs[0]; - } - for (my $i = 1; $i <= $#addrs; $i++) { - $fixedaddrs[$i] = AddressSub($addrs[$i], "0x1"); - } - return join $delimiter, @fixedaddrs; - } -} - -# CPU profile reader -sub ReadCPUProfile { - my $prog = shift; - my $fname = shift; # just used for logging - local *PROFILE = shift; - my $version; - my $period; - my $i; - my $profile = {}; - my $pcs = {}; - - # Parse string into array of slots. - my $slots = CpuProfileStream->new(*PROFILE, $fname); - - # Read header. The current header version is a 5-element structure - # containing: - # 0: header count (always 0) - # 1: header "words" (after this one: 3) - # 2: format version (0) - # 3: sampling period (usec) - # 4: unused padding (always 0) - if ($slots->get(0) != 0 ) { - error("$fname: not a profile file, or old format profile file\n"); - } - $i = 2 + $slots->get(1); - $version = $slots->get(2); - $period = $slots->get(3); - # Do some sanity checking on these header values. - if ($version > (2**32) || $period > (2**32) || $i > (2**32) || $i < 5) { - error("$fname: not a profile file, or corrupted profile file\n"); - } - - # Parse profile - while ($slots->get($i) != -1) { - my $n = $slots->get($i++); - my $d = $slots->get($i++); - if ($d > (2**16)) { # TODO(csilvers): what's a reasonable max-stack-depth? - my $addr = sprintf("0%o", $i * ($address_length == 8 ? 4 : 8)); - print STDERR "At index $i (address $addr):\n"; - error("$fname: stack trace depth >= 2**32\n"); - } - if ($slots->get($i) == 0) { - # End of profile data marker - $i += $d; - last; - } - - # Make key out of the stack entries - my @k = (); - for (my $j = 0; $j < $d; $j++) { - my $pc = $slots->get($i+$j); - # Subtract one from caller pc so we map back to call instr. - $pc--; - $pc = sprintf("%0*x", $address_length, $pc); - $pcs->{$pc} = 1; - push @k, $pc; - } - - AddEntry($profile, (join "\n", @k), $n); - $i += $d; - } - - # Parse map - my $map = ''; - seek(PROFILE, $i * 4, 0); - read(PROFILE, $map, (stat PROFILE)[7]); - - my $r = {}; - $r->{version} = $version; - $r->{period} = $period; - $r->{profile} = $profile; - $r->{libs} = ParseLibraries($prog, $map, $pcs); - $r->{pcs} = $pcs; - - return $r; -} - -sub HeapProfileIndex { - my $index = 1; - if ($main::opt_inuse_space) { - $index = 1; - } elsif ($main::opt_inuse_objects) { - $index = 0; - } elsif ($main::opt_alloc_space) { - $index = 3; - } elsif ($main::opt_alloc_objects) { - $index = 2; - } - return $index; -} - -sub ReadMappedLibraries { - my $fh = shift; - my $map = ""; - # Read the /proc/self/maps data - while (<$fh>) { - s/\r//g; # turn windows-looking lines into unix-looking lines - $map .= $_; - } - return $map; -} - -sub ReadMemoryMap { - my $fh = shift; - my $map = ""; - # Read /proc/self/maps data as formatted by DumpAddressMap() - my $buildvar = ""; - while (<PROFILE>) { - s/\r//g; # turn windows-looking lines into unix-looking lines - # Parse "build=<dir>" specification if supplied - if (m/^\s*build=(.*)\n/) { - $buildvar = $1; - } - - # Expand "$build" variable if available - $_ =~ s/\$build\b/$buildvar/g; - - $map .= $_; - } - return $map; -} - -sub AdjustSamples { - my ($sample_adjustment, $sampling_algorithm, $n1, $s1, $n2, $s2) = @_; - if ($sample_adjustment) { - if ($sampling_algorithm == 2) { - # Remote-heap version 2 - # The sampling frequency is the rate of a Poisson process. - # This means that the probability of sampling an allocation of - # size X with sampling rate Y is 1 - exp(-X/Y) - if ($n1 != 0) { - my $ratio = (($s1*1.0)/$n1)/($sample_adjustment); - my $scale_factor = 1/(1 - exp(-$ratio)); - $n1 *= $scale_factor; - $s1 *= $scale_factor; - } - if ($n2 != 0) { - my $ratio = (($s2*1.0)/$n2)/($sample_adjustment); - my $scale_factor = 1/(1 - exp(-$ratio)); - $n2 *= $scale_factor; - $s2 *= $scale_factor; - } - } else { - # Remote-heap version 1 - my $ratio; - $ratio = (($s1*1.0)/$n1)/($sample_adjustment); - if ($ratio < 1) { - $n1 /= $ratio; - $s1 /= $ratio; - } - $ratio = (($s2*1.0)/$n2)/($sample_adjustment); - if ($ratio < 1) { - $n2 /= $ratio; - $s2 /= $ratio; - } - } - } - return ($n1, $s1, $n2, $s2); -} - -sub ReadHeapProfile { - my $prog = shift; - local *PROFILE = shift; - my $header = shift; - - my $index = HeapProfileIndex(); - - # Find the type of this profile. The header line looks like: - # heap profile: 1246: 8800744 [ 1246: 8800744] @ <heap-url>/266053 - # There are two pairs <count: size>, the first inuse objects/space, and the - # second allocated objects/space. This is followed optionally by a profile - # type, and if that is present, optionally by a sampling frequency. - # For remote heap profiles (v1): - # The interpretation of the sampling frequency is that the profiler, for - # each sample, calculates a uniformly distributed random integer less than - # the given value, and records the next sample after that many bytes have - # been allocated. Therefore, the expected sample interval is half of the - # given frequency. By default, if not specified, the expected sample - # interval is 128KB. Only remote-heap-page profiles are adjusted for - # sample size. - # For remote heap profiles (v2): - # The sampling frequency is the rate of a Poisson process. This means that - # the probability of sampling an allocation of size X with sampling rate Y - # is 1 - exp(-X/Y) - # For version 2, a typical header line might look like this: - # heap profile: 1922: 127792360 [ 1922: 127792360] @ <heap-url>_v2/524288 - # the trailing number (524288) is the sampling rate. (Version 1 showed - # double the 'rate' here) - my $sampling_algorithm = 0; - my $sample_adjustment = 0; - chomp($header); - my $type = "unknown"; - if ($header =~ m"^heap profile:\s*(\d+):\s+(\d+)\s+\[\s*(\d+):\s+(\d+)\](\s*@\s*([^/]*)(/(\d+))?)?") { - if (defined($6) && ($6 ne '')) { - $type = $6; - my $sample_period = $8; - # $type is "heapprofile" for profiles generated by the - # heap-profiler, and either "heap" or "heap_v2" for profiles - # generated by sampling directly within tcmalloc. It can also - # be "growth" for heap-growth profiles. The first is typically - # found for profiles generated locally, and the others for - # remote profiles. - if (($type eq "heapprofile") || ($type !~ /heap/) ) { - # No need to adjust for the sampling rate with heap-profiler-derived data - $sampling_algorithm = 0; - } elsif ($type =~ /_v2/) { - $sampling_algorithm = 2; # version 2 sampling - if (defined($sample_period) && ($sample_period ne '')) { - $sample_adjustment = int($sample_period); - } - } else { - $sampling_algorithm = 1; # version 1 sampling - if (defined($sample_period) && ($sample_period ne '')) { - $sample_adjustment = int($sample_period)/2; - } - } - } else { - # We detect whether or not this is a remote-heap profile by checking - # that the total-allocated stats ($n2,$s2) are exactly the - # same as the in-use stats ($n1,$s1). It is remotely conceivable - # that a non-remote-heap profile may pass this check, but it is hard - # to imagine how that could happen. - # In this case it's so old it's guaranteed to be remote-heap version 1. - my ($n1, $s1, $n2, $s2) = ($1, $2, $3, $4); - if (($n1 == $n2) && ($s1 == $s2)) { - # This is likely to be a remote-heap based sample profile - $sampling_algorithm = 1; - } - } - } - - if ($sampling_algorithm > 0) { - # For remote-heap generated profiles, adjust the counts and sizes to - # account for the sample rate (we sample once every 128KB by default). - if ($sample_adjustment == 0) { - # Turn on profile adjustment. - $sample_adjustment = 128*1024; - print STDERR "Adjusting heap profiles for 1-in-128KB sampling rate\n"; - } else { - printf STDERR ("Adjusting heap profiles for 1-in-%d sampling rate\n", - $sample_adjustment); - } - if ($sampling_algorithm > 1) { - # We don't bother printing anything for the original version (version 1) - printf STDERR "Heap version $sampling_algorithm\n"; - } - } - - my $profile = {}; - my $pcs = {}; - my $map = ""; - - while (<PROFILE>) { - s/\r//g; # turn windows-looking lines into unix-looking lines - if (/^MAPPED_LIBRARIES:/) { - $map .= ReadMappedLibraries(*PROFILE); - last; - } - - if (/^--- Memory map:/) { - $map .= ReadMemoryMap(*PROFILE); - last; - } - - # Read entry of the form: - # <count1>: <bytes1> [<count2>: <bytes2>] @ a1 a2 a3 ... an - s/^\s*//; - s/\s*$//; - if (m/^\s*(\d+):\s+(\d+)\s+\[\s*(\d+):\s+(\d+)\]\s+@\s+(.*)$/) { - my $stack = $5; - my ($n1, $s1, $n2, $s2) = ($1, $2, $3, $4); - my @counts = AdjustSamples($sample_adjustment, $sampling_algorithm, - $n1, $s1, $n2, $s2); - AddEntries($profile, $pcs, FixCallerAddresses($stack), $counts[$index]); - } - } - - my $r = {}; - $r->{version} = "heap"; - $r->{period} = 1; - $r->{profile} = $profile; - $r->{libs} = ParseLibraries($prog, $map, $pcs); - $r->{pcs} = $pcs; - return $r; -} - -sub ReadThreadedHeapProfile { - my ($prog, $fname, $header) = @_; - - my $index = HeapProfileIndex(); - my $sampling_algorithm = 0; - my $sample_adjustment = 0; - chomp($header); - my $type = "unknown"; - # Assuming a very specific type of header for now. - if ($header =~ m"^heap_v2/(\d+)") { - $type = "_v2"; - $sampling_algorithm = 2; - $sample_adjustment = int($1); - } - if ($type ne "_v2" || !defined($sample_adjustment)) { - die "Threaded heap profiles require v2 sampling with a sample rate\n"; - } - - my $profile = {}; - my $thread_profiles = {}; - my $pcs = {}; - my $map = ""; - my $stack = ""; - - while (<PROFILE>) { - s/\r//g; - if (/^MAPPED_LIBRARIES:/) { - $map .= ReadMappedLibraries(*PROFILE); - last; - } - - if (/^--- Memory map:/) { - $map .= ReadMemoryMap(*PROFILE); - last; - } - - # Read entry of the form: - # @ a1 a2 ... an - # t*: <count1>: <bytes1> [<count2>: <bytes2>] - # t1: <count1>: <bytes1> [<count2>: <bytes2>] - # ... - # tn: <count1>: <bytes1> [<count2>: <bytes2>] - s/^\s*//; - s/\s*$//; - if (m/^@\s+(.*)$/) { - $stack = $1; - } elsif (m/^\s*(t(\*|\d+)):\s+(\d+):\s+(\d+)\s+\[\s*(\d+):\s+(\d+)\]$/) { - if ($stack eq "") { - # Still in the header, so this is just a per-thread summary. - next; - } - my $thread = $2; - my ($n1, $s1, $n2, $s2) = ($3, $4, $5, $6); - my @counts = AdjustSamples($sample_adjustment, $sampling_algorithm, - $n1, $s1, $n2, $s2); - if ($thread eq "*") { - AddEntries($profile, $pcs, FixCallerAddresses($stack), $counts[$index]); - } else { - if (!exists($thread_profiles->{$thread})) { - $thread_profiles->{$thread} = {}; - } - AddEntries($thread_profiles->{$thread}, $pcs, - FixCallerAddresses($stack), $counts[$index]); - } - } - } - - my $r = {}; - $r->{version} = "heap"; - $r->{period} = 1; - $r->{profile} = $profile; - $r->{threads} = $thread_profiles; - $r->{libs} = ParseLibraries($prog, $map, $pcs); - $r->{pcs} = $pcs; - return $r; -} - -sub ReadSynchProfile { - my $prog = shift; - local *PROFILE = shift; - my $header = shift; - - my $map = ''; - my $profile = {}; - my $pcs = {}; - my $sampling_period = 1; - my $cyclespernanosec = 2.8; # Default assumption for old binaries - my $seen_clockrate = 0; - my $line; - - my $index = 0; - if ($main::opt_total_delay) { - $index = 0; - } elsif ($main::opt_contentions) { - $index = 1; - } elsif ($main::opt_mean_delay) { - $index = 2; - } - - while ( $line = <PROFILE> ) { - $line =~ s/\r//g; # turn windows-looking lines into unix-looking lines - if ( $line =~ /^\s*(\d+)\s+(\d+) \@\s*(.*?)\s*$/ ) { - my ($cycles, $count, $stack) = ($1, $2, $3); - - # Convert cycles to nanoseconds - $cycles /= $cyclespernanosec; - - # Adjust for sampling done by application - $cycles *= $sampling_period; - $count *= $sampling_period; - - my @values = ($cycles, $count, $cycles / $count); - AddEntries($profile, $pcs, FixCallerAddresses($stack), $values[$index]); - - } elsif ( $line =~ /^(slow release).*thread \d+ \@\s*(.*?)\s*$/ || - $line =~ /^\s*(\d+) \@\s*(.*?)\s*$/ ) { - my ($cycles, $stack) = ($1, $2); - if ($cycles !~ /^\d+$/) { - next; - } - - # Convert cycles to nanoseconds - $cycles /= $cyclespernanosec; - - # Adjust for sampling done by application - $cycles *= $sampling_period; - - AddEntries($profile, $pcs, FixCallerAddresses($stack), $cycles); - - } elsif ( $line =~ m/^([a-z][^=]*)=(.*)$/ ) { - my ($variable, $value) = ($1,$2); - for ($variable, $value) { - s/^\s+//; - s/\s+$//; - } - if ($variable eq "cycles/second") { - $cyclespernanosec = $value / 1e9; - $seen_clockrate = 1; - } elsif ($variable eq "sampling period") { - $sampling_period = $value; - } elsif ($variable eq "ms since reset") { - # Currently nothing is done with this value in jeprof - # So we just silently ignore it for now - } elsif ($variable eq "discarded samples") { - # Currently nothing is done with this value in jeprof - # So we just silently ignore it for now - } else { - printf STDERR ("Ignoring unnknown variable in /contention output: " . - "'%s' = '%s'\n",$variable,$value); - } - } else { - # Memory map entry - $map .= $line; - } - } - - if (!$seen_clockrate) { - printf STDERR ("No cycles/second entry in profile; Guessing %.1f GHz\n", - $cyclespernanosec); - } - - my $r = {}; - $r->{version} = 0; - $r->{period} = $sampling_period; - $r->{profile} = $profile; - $r->{libs} = ParseLibraries($prog, $map, $pcs); - $r->{pcs} = $pcs; - return $r; -} - -# Given a hex value in the form "0x1abcd" or "1abcd", return either -# "0001abcd" or "000000000001abcd", depending on the current (global) -# address length. -sub HexExtend { - my $addr = shift; - - $addr =~ s/^(0x)?0*//; - my $zeros_needed = $address_length - length($addr); - if ($zeros_needed < 0) { - printf STDERR "Warning: address $addr is longer than address length $address_length\n"; - return $addr; - } - return ("0" x $zeros_needed) . $addr; -} - -##### Symbol extraction ##### - -# Aggressively search the lib_prefix values for the given library -# If all else fails, just return the name of the library unmodified. -# If the lib_prefix is "/my/path,/other/path" and $file is "/lib/dir/mylib.so" -# it will search the following locations in this order, until it finds a file: -# /my/path/lib/dir/mylib.so -# /other/path/lib/dir/mylib.so -# /my/path/dir/mylib.so -# /other/path/dir/mylib.so -# /my/path/mylib.so -# /other/path/mylib.so -# /lib/dir/mylib.so (returned as last resort) -sub FindLibrary { - my $file = shift; - my $suffix = $file; - - # Search for the library as described above - do { - foreach my $prefix (@prefix_list) { - my $fullpath = $prefix . $suffix; - if (-e $fullpath) { - return $fullpath; - } - } - } while ($suffix =~ s|^/[^/]+/|/|); - return $file; -} - -# Return path to library with debugging symbols. -# For libc libraries, the copy in /usr/lib/debug contains debugging symbols -sub DebuggingLibrary { - my $file = shift; - if ($file =~ m|^/|) { - if (-f "/usr/lib/debug$file") { - return "/usr/lib/debug$file"; - } elsif (-f "/usr/lib/debug$file.debug") { - return "/usr/lib/debug$file.debug"; - } - } - return undef; -} - -# Parse text section header of a library using objdump -sub ParseTextSectionHeaderFromObjdump { - my $lib = shift; - - my $size = undef; - my $vma; - my $file_offset; - # Get objdump output from the library file to figure out how to - # map between mapped addresses and addresses in the library. - my $cmd = ShellEscape($obj_tool_map{"objdump"}, "-h", $lib); - open(OBJDUMP, "$cmd |") || error("$cmd: $!\n"); - while (<OBJDUMP>) { - s/\r//g; # turn windows-looking lines into unix-looking lines - # Idx Name Size VMA LMA File off Algn - # 10 .text 00104b2c 420156f0 420156f0 000156f0 2**4 - # For 64-bit objects, VMA and LMA will be 16 hex digits, size and file - # offset may still be 8. But AddressSub below will still handle that. - my @x = split; - if (($#x >= 6) && ($x[1] eq '.text')) { - $size = $x[2]; - $vma = $x[3]; - $file_offset = $x[5]; - last; - } - } - close(OBJDUMP); - - if (!defined($size)) { - return undef; - } - - my $r = {}; - $r->{size} = $size; - $r->{vma} = $vma; - $r->{file_offset} = $file_offset; - - return $r; -} - -# Parse text section header of a library using otool (on OS X) -sub ParseTextSectionHeaderFromOtool { - my $lib = shift; - - my $size = undef; - my $vma = undef; - my $file_offset = undef; - # Get otool output from the library file to figure out how to - # map between mapped addresses and addresses in the library. - my $command = ShellEscape($obj_tool_map{"otool"}, "-l", $lib); - open(OTOOL, "$command |") || error("$command: $!\n"); - my $cmd = ""; - my $sectname = ""; - my $segname = ""; - foreach my $line (<OTOOL>) { - $line =~ s/\r//g; # turn windows-looking lines into unix-looking lines - # Load command <#> - # cmd LC_SEGMENT - # [...] - # Section - # sectname __text - # segname __TEXT - # addr 0x000009f8 - # size 0x00018b9e - # offset 2552 - # align 2^2 (4) - # We will need to strip off the leading 0x from the hex addresses, - # and convert the offset into hex. - if ($line =~ /Load command/) { - $cmd = ""; - $sectname = ""; - $segname = ""; - } elsif ($line =~ /Section/) { - $sectname = ""; - $segname = ""; - } elsif ($line =~ /cmd (\w+)/) { - $cmd = $1; - } elsif ($line =~ /sectname (\w+)/) { - $sectname = $1; - } elsif ($line =~ /segname (\w+)/) { - $segname = $1; - } elsif (!(($cmd eq "LC_SEGMENT" || $cmd eq "LC_SEGMENT_64") && - $sectname eq "__text" && - $segname eq "__TEXT")) { - next; - } elsif ($line =~ /\baddr 0x([0-9a-fA-F]+)/) { - $vma = $1; - } elsif ($line =~ /\bsize 0x([0-9a-fA-F]+)/) { - $size = $1; - } elsif ($line =~ /\boffset ([0-9]+)/) { - $file_offset = sprintf("%016x", $1); - } - if (defined($vma) && defined($size) && defined($file_offset)) { - last; - } - } - close(OTOOL); - - if (!defined($vma) || !defined($size) || !defined($file_offset)) { - return undef; - } - - my $r = {}; - $r->{size} = $size; - $r->{vma} = $vma; - $r->{file_offset} = $file_offset; - - return $r; -} - -sub ParseTextSectionHeader { - # obj_tool_map("otool") is only defined if we're in a Mach-O environment - if (defined($obj_tool_map{"otool"})) { - my $r = ParseTextSectionHeaderFromOtool(@_); - if (defined($r)){ - return $r; - } - } - # If otool doesn't work, or we don't have it, fall back to objdump - return ParseTextSectionHeaderFromObjdump(@_); -} - -# Split /proc/pid/maps dump into a list of libraries -sub ParseLibraries { - return if $main::use_symbol_page; # We don't need libraries info. - my $prog = Cwd::abs_path(shift); - my $map = shift; - my $pcs = shift; - - my $result = []; - my $h = "[a-f0-9]+"; - my $zero_offset = HexExtend("0"); - - my $buildvar = ""; - foreach my $l (split("\n", $map)) { - if ($l =~ m/^\s*build=(.*)$/) { - $buildvar = $1; - } - - my $start; - my $finish; - my $offset; - my $lib; - if ($l =~ /^($h)-($h)\s+..x.\s+($h)\s+\S+:\S+\s+\d+\s+(\S+\.(so|dll|dylib|bundle)((\.\d+)+\w*(\.\d+){0,3})?)$/i) { - # Full line from /proc/self/maps. Example: - # 40000000-40015000 r-xp 00000000 03:01 12845071 /lib/ld-2.3.2.so - $start = HexExtend($1); - $finish = HexExtend($2); - $offset = HexExtend($3); - $lib = $4; - $lib =~ s|\\|/|g; # turn windows-style paths into unix-style paths - } elsif ($l =~ /^\s*($h)-($h):\s*(\S+\.so(\.\d+)*)/) { - # Cooked line from DumpAddressMap. Example: - # 40000000-40015000: /lib/ld-2.3.2.so - $start = HexExtend($1); - $finish = HexExtend($2); - $offset = $zero_offset; - $lib = $3; - } elsif (($l =~ /^($h)-($h)\s+..x.\s+($h)\s+\S+:\S+\s+\d+\s+(\S+)$/i) && ($4 eq $prog)) { - # PIEs and address space randomization do not play well with our - # default assumption that main executable is at lowest - # addresses. So we're detecting main executable in - # /proc/self/maps as well. - $start = HexExtend($1); - $finish = HexExtend($2); - $offset = HexExtend($3); - $lib = $4; - $lib =~ s|\\|/|g; # turn windows-style paths into unix-style paths - } - # FreeBSD 10.0 virtual memory map /proc/curproc/map as defined in - # function procfs_doprocmap (sys/fs/procfs/procfs_map.c) - # - # Example: - # 0x800600000 0x80061a000 26 0 0xfffff800035a0000 r-x 75 33 0x1004 COW NC vnode /libexec/ld-elf.s - # o.1 NCH -1 - elsif ($l =~ /^(0x$h)\s(0x$h)\s\d+\s\d+\s0x$h\sr-x\s\d+\s\d+\s0x\d+\s(COW|NCO)\s(NC|NNC)\svnode\s(\S+\.so(\.\d+)*)/) { - $start = HexExtend($1); - $finish = HexExtend($2); - $offset = $zero_offset; - $lib = FindLibrary($5); - - } else { - next; - } - - # Expand "$build" variable if available - $lib =~ s/\$build\b/$buildvar/g; - - $lib = FindLibrary($lib); - - # Check for pre-relocated libraries, which use pre-relocated symbol tables - # and thus require adjusting the offset that we'll use to translate - # VM addresses into symbol table addresses. - # Only do this if we're not going to fetch the symbol table from a - # debugging copy of the library. - if (!DebuggingLibrary($lib)) { - my $text = ParseTextSectionHeader($lib); - if (defined($text)) { - my $vma_offset = AddressSub($text->{vma}, $text->{file_offset}); - $offset = AddressAdd($offset, $vma_offset); - } - } - - if($main::opt_debug) { printf STDERR "$start:$finish ($offset) $lib\n"; } - push(@{$result}, [$lib, $start, $finish, $offset]); - } - - # Append special entry for additional library (not relocated) - if ($main::opt_lib ne "") { - my $text = ParseTextSectionHeader($main::opt_lib); - if (defined($text)) { - my $start = $text->{vma}; - my $finish = AddressAdd($start, $text->{size}); - - push(@{$result}, [$main::opt_lib, $start, $finish, $start]); - } - } - - # Append special entry for the main program. This covers - # 0..max_pc_value_seen, so that we assume pc values not found in one - # of the library ranges will be treated as coming from the main - # program binary. - my $min_pc = HexExtend("0"); - my $max_pc = $min_pc; # find the maximal PC value in any sample - foreach my $pc (keys(%{$pcs})) { - if (HexExtend($pc) gt $max_pc) { $max_pc = HexExtend($pc); } - } - push(@{$result}, [$prog, $min_pc, $max_pc, $zero_offset]); - - return $result; -} - -# Add two hex addresses of length $address_length. -# Run jeprof --test for unit test if this is changed. -sub AddressAdd { - my $addr1 = shift; - my $addr2 = shift; - my $sum; - - if ($address_length == 8) { - # Perl doesn't cope with wraparound arithmetic, so do it explicitly: - $sum = (hex($addr1)+hex($addr2)) % (0x10000000 * 16); - return sprintf("%08x", $sum); - - } else { - # Do the addition in 7-nibble chunks to trivialize carry handling. - - if ($main::opt_debug and $main::opt_test) { - print STDERR "AddressAdd $addr1 + $addr2 = "; - } - - my $a1 = substr($addr1,-7); - $addr1 = substr($addr1,0,-7); - my $a2 = substr($addr2,-7); - $addr2 = substr($addr2,0,-7); - $sum = hex($a1) + hex($a2); - my $c = 0; - if ($sum > 0xfffffff) { - $c = 1; - $sum -= 0x10000000; - } - my $r = sprintf("%07x", $sum); - - $a1 = substr($addr1,-7); - $addr1 = substr($addr1,0,-7); - $a2 = substr($addr2,-7); - $addr2 = substr($addr2,0,-7); - $sum = hex($a1) + hex($a2) + $c; - $c = 0; - if ($sum > 0xfffffff) { - $c = 1; - $sum -= 0x10000000; - } - $r = sprintf("%07x", $sum) . $r; - - $sum = hex($addr1) + hex($addr2) + $c; - if ($sum > 0xff) { $sum -= 0x100; } - $r = sprintf("%02x", $sum) . $r; - - if ($main::opt_debug and $main::opt_test) { print STDERR "$r\n"; } - - return $r; - } -} - - -# Subtract two hex addresses of length $address_length. -# Run jeprof --test for unit test if this is changed. -sub AddressSub { - my $addr1 = shift; - my $addr2 = shift; - my $diff; - - if ($address_length == 8) { - # Perl doesn't cope with wraparound arithmetic, so do it explicitly: - $diff = (hex($addr1)-hex($addr2)) % (0x10000000 * 16); - return sprintf("%08x", $diff); - - } else { - # Do the addition in 7-nibble chunks to trivialize borrow handling. - # if ($main::opt_debug) { print STDERR "AddressSub $addr1 - $addr2 = "; } - - my $a1 = hex(substr($addr1,-7)); - $addr1 = substr($addr1,0,-7); - my $a2 = hex(substr($addr2,-7)); - $addr2 = substr($addr2,0,-7); - my $b = 0; - if ($a2 > $a1) { - $b = 1; - $a1 += 0x10000000; - } - $diff = $a1 - $a2; - my $r = sprintf("%07x", $diff); - - $a1 = hex(substr($addr1,-7)); - $addr1 = substr($addr1,0,-7); - $a2 = hex(substr($addr2,-7)) + $b; - $addr2 = substr($addr2,0,-7); - $b = 0; - if ($a2 > $a1) { - $b = 1; - $a1 += 0x10000000; - } - $diff = $a1 - $a2; - $r = sprintf("%07x", $diff) . $r; - - $a1 = hex($addr1); - $a2 = hex($addr2) + $b; - if ($a2 > $a1) { $a1 += 0x100; } - $diff = $a1 - $a2; - $r = sprintf("%02x", $diff) . $r; - - # if ($main::opt_debug) { print STDERR "$r\n"; } - - return $r; - } -} - -# Increment a hex addresses of length $address_length. -# Run jeprof --test for unit test if this is changed. -sub AddressInc { - my $addr = shift; - my $sum; - - if ($address_length == 8) { - # Perl doesn't cope with wraparound arithmetic, so do it explicitly: - $sum = (hex($addr)+1) % (0x10000000 * 16); - return sprintf("%08x", $sum); - - } else { - # Do the addition in 7-nibble chunks to trivialize carry handling. - # We are always doing this to step through the addresses in a function, - # and will almost never overflow the first chunk, so we check for this - # case and exit early. - - # if ($main::opt_debug) { print STDERR "AddressInc $addr1 = "; } - - my $a1 = substr($addr,-7); - $addr = substr($addr,0,-7); - $sum = hex($a1) + 1; - my $r = sprintf("%07x", $sum); - if ($sum <= 0xfffffff) { - $r = $addr . $r; - # if ($main::opt_debug) { print STDERR "$r\n"; } - return HexExtend($r); - } else { - $r = "0000000"; - } - - $a1 = substr($addr,-7); - $addr = substr($addr,0,-7); - $sum = hex($a1) + 1; - $r = sprintf("%07x", $sum) . $r; - if ($sum <= 0xfffffff) { - $r = $addr . $r; - # if ($main::opt_debug) { print STDERR "$r\n"; } - return HexExtend($r); - } else { - $r = "00000000000000"; - } - - $sum = hex($addr) + 1; - if ($sum > 0xff) { $sum -= 0x100; } - $r = sprintf("%02x", $sum) . $r; - - # if ($main::opt_debug) { print STDERR "$r\n"; } - return $r; - } -} - -# Extract symbols for all PC values found in profile -sub ExtractSymbols { - my $libs = shift; - my $pcset = shift; - - my $symbols = {}; - - # Map each PC value to the containing library. To make this faster, - # we sort libraries by their starting pc value (highest first), and - # advance through the libraries as we advance the pc. Sometimes the - # addresses of libraries may overlap with the addresses of the main - # binary, so to make sure the libraries 'win', we iterate over the - # libraries in reverse order (which assumes the binary doesn't start - # in the middle of a library, which seems a fair assumption). - my @pcs = (sort { $a cmp $b } keys(%{$pcset})); # pcset is 0-extended strings - foreach my $lib (sort {$b->[1] cmp $a->[1]} @{$libs}) { - my $libname = $lib->[0]; - my $start = $lib->[1]; - my $finish = $lib->[2]; - my $offset = $lib->[3]; - - # Use debug library if it exists - my $debug_libname = DebuggingLibrary($libname); - if ($debug_libname) { - $libname = $debug_libname; - } - - # Get list of pcs that belong in this library. - my $contained = []; - my ($start_pc_index, $finish_pc_index); - # Find smallest finish_pc_index such that $finish < $pc[$finish_pc_index]. - for ($finish_pc_index = $#pcs + 1; $finish_pc_index > 0; - $finish_pc_index--) { - last if $pcs[$finish_pc_index - 1] le $finish; - } - # Find smallest start_pc_index such that $start <= $pc[$start_pc_index]. - for ($start_pc_index = $finish_pc_index; $start_pc_index > 0; - $start_pc_index--) { - last if $pcs[$start_pc_index - 1] lt $start; - } - # This keeps PC values higher than $pc[$finish_pc_index] in @pcs, - # in case there are overlaps in libraries and the main binary. - @{$contained} = splice(@pcs, $start_pc_index, - $finish_pc_index - $start_pc_index); - # Map to symbols - MapToSymbols($libname, AddressSub($start, $offset), $contained, $symbols); - } - - return $symbols; -} - -# Map list of PC values to symbols for a given image -sub MapToSymbols { - my $image = shift; - my $offset = shift; - my $pclist = shift; - my $symbols = shift; - - my $debug = 0; - - # Ignore empty binaries - if ($#{$pclist} < 0) { return; } - - # Figure out the addr2line command to use - my $addr2line = $obj_tool_map{"addr2line"}; - my $cmd = ShellEscape($addr2line, "-f", "-C", "-e", $image); - if (exists $obj_tool_map{"addr2line_pdb"}) { - $addr2line = $obj_tool_map{"addr2line_pdb"}; - $cmd = ShellEscape($addr2line, "--demangle", "-f", "-C", "-e", $image); - } - - # If "addr2line" isn't installed on the system at all, just use - # nm to get what info we can (function names, but not line numbers). - if (system(ShellEscape($addr2line, "--help") . " >$dev_null 2>&1") != 0) { - MapSymbolsWithNM($image, $offset, $pclist, $symbols); - return; - } - - # "addr2line -i" can produce a variable number of lines per input - # address, with no separator that allows us to tell when data for - # the next address starts. So we find the address for a special - # symbol (_fini) and interleave this address between all real - # addresses passed to addr2line. The name of this special symbol - # can then be used as a separator. - $sep_address = undef; # May be filled in by MapSymbolsWithNM() - my $nm_symbols = {}; - MapSymbolsWithNM($image, $offset, $pclist, $nm_symbols); - if (defined($sep_address)) { - # Only add " -i" to addr2line if the binary supports it. - # addr2line --help returns 0, but not if it sees an unknown flag first. - if (system("$cmd -i --help >$dev_null 2>&1") == 0) { - $cmd .= " -i"; - } else { - $sep_address = undef; # no need for sep_address if we don't support -i - } - } - - # Make file with all PC values with intervening 'sep_address' so - # that we can reliably detect the end of inlined function list - open(ADDRESSES, ">$main::tmpfile_sym") || error("$main::tmpfile_sym: $!\n"); - if ($debug) { print("---- $image ---\n"); } - for (my $i = 0; $i <= $#{$pclist}; $i++) { - # addr2line always reads hex addresses, and does not need '0x' prefix. - if ($debug) { printf STDERR ("%s\n", $pclist->[$i]); } - printf ADDRESSES ("%s\n", AddressSub($pclist->[$i], $offset)); - if (defined($sep_address)) { - printf ADDRESSES ("%s\n", $sep_address); - } - } - close(ADDRESSES); - if ($debug) { - print("----\n"); - system("cat", $main::tmpfile_sym); - print("----\n"); - system("$cmd < " . ShellEscape($main::tmpfile_sym)); - print("----\n"); - } - - open(SYMBOLS, "$cmd <" . ShellEscape($main::tmpfile_sym) . " |") - || error("$cmd: $!\n"); - my $count = 0; # Index in pclist - while (<SYMBOLS>) { - # Read fullfunction and filelineinfo from next pair of lines - s/\r?\n$//g; - my $fullfunction = $_; - $_ = <SYMBOLS>; - s/\r?\n$//g; - my $filelinenum = $_; - - if (defined($sep_address) && $fullfunction eq $sep_symbol) { - # Terminating marker for data for this address - $count++; - next; - } - - $filelinenum =~ s|\\|/|g; # turn windows-style paths into unix-style paths - - my $pcstr = $pclist->[$count]; - my $function = ShortFunctionName($fullfunction); - my $nms = $nm_symbols->{$pcstr}; - if (defined($nms)) { - if ($fullfunction eq '??') { - # nm found a symbol for us. - $function = $nms->[0]; - $fullfunction = $nms->[2]; - } else { - # MapSymbolsWithNM tags each routine with its starting address, - # useful in case the image has multiple occurrences of this - # routine. (It uses a syntax that resembles template paramters, - # that are automatically stripped out by ShortFunctionName().) - # addr2line does not provide the same information. So we check - # if nm disambiguated our symbol, and if so take the annotated - # (nm) version of the routine-name. TODO(csilvers): this won't - # catch overloaded, inlined symbols, which nm doesn't see. - # Better would be to do a check similar to nm's, in this fn. - if ($nms->[2] =~ m/^\Q$function\E/) { # sanity check it's the right fn - $function = $nms->[0]; - $fullfunction = $nms->[2]; - } - } - } - - # Prepend to accumulated symbols for pcstr - # (so that caller comes before callee) - my $sym = $symbols->{$pcstr}; - if (!defined($sym)) { - $sym = []; - $symbols->{$pcstr} = $sym; - } - unshift(@{$sym}, $function, $filelinenum, $fullfunction); - if ($debug) { printf STDERR ("%s => [%s]\n", $pcstr, join(" ", @{$sym})); } - if (!defined($sep_address)) { - # Inlining is off, so this entry ends immediately - $count++; - } - } - close(SYMBOLS); -} - -# Use nm to map the list of referenced PCs to symbols. Return true iff we -# are able to read procedure information via nm. -sub MapSymbolsWithNM { - my $image = shift; - my $offset = shift; - my $pclist = shift; - my $symbols = shift; - - # Get nm output sorted by increasing address - my $symbol_table = GetProcedureBoundaries($image, "."); - if (!%{$symbol_table}) { - return 0; - } - # Start addresses are already the right length (8 or 16 hex digits). - my @names = sort { $symbol_table->{$a}->[0] cmp $symbol_table->{$b}->[0] } - keys(%{$symbol_table}); - - if ($#names < 0) { - # No symbols: just use addresses - foreach my $pc (@{$pclist}) { - my $pcstr = "0x" . $pc; - $symbols->{$pc} = [$pcstr, "?", $pcstr]; - } - return 0; - } - - # Sort addresses so we can do a join against nm output - my $index = 0; - my $fullname = $names[0]; - my $name = ShortFunctionName($fullname); - foreach my $pc (sort { $a cmp $b } @{$pclist}) { - # Adjust for mapped offset - my $mpc = AddressSub($pc, $offset); - while (($index < $#names) && ($mpc ge $symbol_table->{$fullname}->[1])){ - $index++; - $fullname = $names[$index]; - $name = ShortFunctionName($fullname); - } - if ($mpc lt $symbol_table->{$fullname}->[1]) { - $symbols->{$pc} = [$name, "?", $fullname]; - } else { - my $pcstr = "0x" . $pc; - $symbols->{$pc} = [$pcstr, "?", $pcstr]; - } - } - return 1; -} - -sub ShortFunctionName { - my $function = shift; - while ($function =~ s/\([^()]*\)(\s*const)?//g) { } # Argument types - while ($function =~ s/<[^<>]*>//g) { } # Remove template arguments - $function =~ s/^.*\s+(\w+::)/$1/; # Remove leading type - return $function; -} - -# Trim overly long symbols found in disassembler output -sub CleanDisassembly { - my $d = shift; - while ($d =~ s/\([^()%]*\)(\s*const)?//g) { } # Argument types, not (%rax) - while ($d =~ s/(\w+)<[^<>]*>/$1/g) { } # Remove template arguments - return $d; -} - -# Clean file name for display -sub CleanFileName { - my ($f) = @_; - $f =~ s|^/proc/self/cwd/||; - $f =~ s|^\./||; - return $f; -} - -# Make address relative to section and clean up for display -sub UnparseAddress { - my ($offset, $address) = @_; - $address = AddressSub($address, $offset); - $address =~ s/^0x//; - $address =~ s/^0*//; - return $address; -} - -##### Miscellaneous ##### - -# Find the right versions of the above object tools to use. The -# argument is the program file being analyzed, and should be an ELF -# 32-bit or ELF 64-bit executable file. The location of the tools -# is determined by considering the following options in this order: -# 1) --tools option, if set -# 2) JEPROF_TOOLS environment variable, if set -# 3) the environment -sub ConfigureObjTools { - my $prog_file = shift; - - # Check for the existence of $prog_file because /usr/bin/file does not - # predictably return error status in prod. - (-e $prog_file) || error("$prog_file does not exist.\n"); - - my $file_type = undef; - if (-e "/usr/bin/file") { - # Follow symlinks (at least for systems where "file" supports that). - my $escaped_prog_file = ShellEscape($prog_file); - $file_type = `/usr/bin/file -L $escaped_prog_file 2>$dev_null || - /usr/bin/file $escaped_prog_file`; - } elsif ($^O == "MSWin32") { - $file_type = "MS Windows"; - } else { - print STDERR "WARNING: Can't determine the file type of $prog_file"; - } - - if ($file_type =~ /64-bit/) { - # Change $address_length to 16 if the program file is ELF 64-bit. - # We can't detect this from many (most?) heap or lock contention - # profiles, since the actual addresses referenced are generally in low - # memory even for 64-bit programs. - $address_length = 16; - } - - if ($file_type =~ /MS Windows/) { - # For windows, we provide a version of nm and addr2line as part of - # the opensource release, which is capable of parsing - # Windows-style PDB executables. It should live in the path, or - # in the same directory as jeprof. - $obj_tool_map{"nm_pdb"} = "nm-pdb"; - $obj_tool_map{"addr2line_pdb"} = "addr2line-pdb"; - } - - if ($file_type =~ /Mach-O/) { - # OS X uses otool to examine Mach-O files, rather than objdump. - $obj_tool_map{"otool"} = "otool"; - $obj_tool_map{"addr2line"} = "false"; # no addr2line - $obj_tool_map{"objdump"} = "false"; # no objdump - } - - # Go fill in %obj_tool_map with the pathnames to use: - foreach my $tool (keys %obj_tool_map) { - $obj_tool_map{$tool} = ConfigureTool($obj_tool_map{$tool}); - } -} - -# Returns the path of a caller-specified object tool. If --tools or -# JEPROF_TOOLS are specified, then returns the full path to the tool -# with that prefix. Otherwise, returns the path unmodified (which -# means we will look for it on PATH). -sub ConfigureTool { - my $tool = shift; - my $path; - - # --tools (or $JEPROF_TOOLS) is a comma separated list, where each - # item is either a) a pathname prefix, or b) a map of the form - # <tool>:<path>. First we look for an entry of type (b) for our - # tool. If one is found, we use it. Otherwise, we consider all the - # pathname prefixes in turn, until one yields an existing file. If - # none does, we use a default path. - my $tools = $main::opt_tools || $ENV{"JEPROF_TOOLS"} || ""; - if ($tools =~ m/(,|^)\Q$tool\E:([^,]*)/) { - $path = $2; - # TODO(csilvers): sanity-check that $path exists? Hard if it's relative. - } elsif ($tools ne '') { - foreach my $prefix (split(',', $tools)) { - next if ($prefix =~ /:/); # ignore "tool:fullpath" entries in the list - if (-x $prefix . $tool) { - $path = $prefix . $tool; - last; - } - } - if (!$path) { - error("No '$tool' found with prefix specified by " . - "--tools (or \$JEPROF_TOOLS) '$tools'\n"); - } - } else { - # ... otherwise use the version that exists in the same directory as - # jeprof. If there's nothing there, use $PATH. - $0 =~ m,[^/]*$,; # this is everything after the last slash - my $dirname = $`; # this is everything up to and including the last slash - if (-x "$dirname$tool") { - $path = "$dirname$tool"; - } else { - $path = $tool; - } - } - if ($main::opt_debug) { print STDERR "Using '$path' for '$tool'.\n"; } - return $path; -} - -sub ShellEscape { - my @escaped_words = (); - foreach my $word (@_) { - my $escaped_word = $word; - if ($word =~ m![^a-zA-Z0-9/.,_=-]!) { # check for anything not in whitelist - $escaped_word =~ s/'/'\\''/; - $escaped_word = "'$escaped_word'"; - } - push(@escaped_words, $escaped_word); - } - return join(" ", @escaped_words); -} - -sub cleanup { - unlink($main::tmpfile_sym); - unlink(keys %main::tempnames); - - # We leave any collected profiles in $HOME/jeprof in case the user wants - # to look at them later. We print a message informing them of this. - if ((scalar(@main::profile_files) > 0) && - defined($main::collected_profile)) { - if (scalar(@main::profile_files) == 1) { - print STDERR "Dynamically gathered profile is in $main::collected_profile\n"; - } - print STDERR "If you want to investigate this profile further, you can do:\n"; - print STDERR "\n"; - print STDERR " jeprof \\\n"; - print STDERR " $main::prog \\\n"; - print STDERR " $main::collected_profile\n"; - print STDERR "\n"; - } -} - -sub sighandler { - cleanup(); - exit(1); -} - -sub error { - my $msg = shift; - print STDERR $msg; - cleanup(); - exit(1); -} - - -# Run $nm_command and get all the resulting procedure boundaries whose -# names match "$regexp" and returns them in a hashtable mapping from -# procedure name to a two-element vector of [start address, end address] -sub GetProcedureBoundariesViaNm { - my $escaped_nm_command = shift; # shell-escaped - my $regexp = shift; - - my $symbol_table = {}; - open(NM, "$escaped_nm_command |") || error("$escaped_nm_command: $!\n"); - my $last_start = "0"; - my $routine = ""; - while (<NM>) { - s/\r//g; # turn windows-looking lines into unix-looking lines - if (m/^\s*([0-9a-f]+) (.) (..*)/) { - my $start_val = $1; - my $type = $2; - my $this_routine = $3; - - # It's possible for two symbols to share the same address, if - # one is a zero-length variable (like __start_google_malloc) or - # one symbol is a weak alias to another (like __libc_malloc). - # In such cases, we want to ignore all values except for the - # actual symbol, which in nm-speak has type "T". The logic - # below does this, though it's a bit tricky: what happens when - # we have a series of lines with the same address, is the first - # one gets queued up to be processed. However, it won't - # *actually* be processed until later, when we read a line with - # a different address. That means that as long as we're reading - # lines with the same address, we have a chance to replace that - # item in the queue, which we do whenever we see a 'T' entry -- - # that is, a line with type 'T'. If we never see a 'T' entry, - # we'll just go ahead and process the first entry (which never - # got touched in the queue), and ignore the others. - if ($start_val eq $last_start && $type =~ /t/i) { - # We are the 'T' symbol at this address, replace previous symbol. - $routine = $this_routine; - next; - } elsif ($start_val eq $last_start) { - # We're not the 'T' symbol at this address, so ignore us. - next; - } - - if ($this_routine eq $sep_symbol) { - $sep_address = HexExtend($start_val); - } - - # Tag this routine with the starting address in case the image - # has multiple occurrences of this routine. We use a syntax - # that resembles template parameters that are automatically - # stripped out by ShortFunctionName() - $this_routine .= "<$start_val>"; - - if (defined($routine) && $routine =~ m/$regexp/) { - $symbol_table->{$routine} = [HexExtend($last_start), - HexExtend($start_val)]; - } - $last_start = $start_val; - $routine = $this_routine; - } elsif (m/^Loaded image name: (.+)/) { - # The win32 nm workalike emits information about the binary it is using. - if ($main::opt_debug) { print STDERR "Using Image $1\n"; } - } elsif (m/^PDB file name: (.+)/) { - # The win32 nm workalike emits information about the pdb it is using. - if ($main::opt_debug) { print STDERR "Using PDB $1\n"; } - } - } - close(NM); - # Handle the last line in the nm output. Unfortunately, we don't know - # how big this last symbol is, because we don't know how big the file - # is. For now, we just give it a size of 0. - # TODO(csilvers): do better here. - if (defined($routine) && $routine =~ m/$regexp/) { - $symbol_table->{$routine} = [HexExtend($last_start), - HexExtend($last_start)]; - } - return $symbol_table; -} - -# Gets the procedure boundaries for all routines in "$image" whose names -# match "$regexp" and returns them in a hashtable mapping from procedure -# name to a two-element vector of [start address, end address]. -# Will return an empty map if nm is not installed or not working properly. -sub GetProcedureBoundaries { - my $image = shift; - my $regexp = shift; - - # If $image doesn't start with /, then put ./ in front of it. This works - # around an obnoxious bug in our probing of nm -f behavior. - # "nm -f $image" is supposed to fail on GNU nm, but if: - # - # a. $image starts with [BbSsPp] (for example, bin/foo/bar), AND - # b. you have a.out in your current directory (a not uncommon occurence) - # - # then "nm -f $image" succeeds because -f only looks at the first letter of - # the argument, which looks valid because it's [BbSsPp], and then since - # there's no image provided, it looks for a.out and finds it. - # - # This regex makes sure that $image starts with . or /, forcing the -f - # parsing to fail since . and / are not valid formats. - $image =~ s#^[^/]#./$&#; - - # For libc libraries, the copy in /usr/lib/debug contains debugging symbols - my $debugging = DebuggingLibrary($image); - if ($debugging) { - $image = $debugging; - } - - my $nm = $obj_tool_map{"nm"}; - my $cppfilt = $obj_tool_map{"c++filt"}; - - # nm can fail for two reasons: 1) $image isn't a debug library; 2) nm - # binary doesn't support --demangle. In addition, for OS X we need - # to use the -f flag to get 'flat' nm output (otherwise we don't sort - # properly and get incorrect results). Unfortunately, GNU nm uses -f - # in an incompatible way. So first we test whether our nm supports - # --demangle and -f. - my $demangle_flag = ""; - my $cppfilt_flag = ""; - my $to_devnull = ">$dev_null 2>&1"; - if (system(ShellEscape($nm, "--demangle", $image) . $to_devnull) == 0) { - # In this mode, we do "nm --demangle <foo>" - $demangle_flag = "--demangle"; - $cppfilt_flag = ""; - } elsif (system(ShellEscape($cppfilt, $image) . $to_devnull) == 0) { - # In this mode, we do "nm <foo> | c++filt" - $cppfilt_flag = " | " . ShellEscape($cppfilt); - }; - my $flatten_flag = ""; - if (system(ShellEscape($nm, "-f", $image) . $to_devnull) == 0) { - $flatten_flag = "-f"; - } - - # Finally, in the case $imagie isn't a debug library, we try again with - # -D to at least get *exported* symbols. If we can't use --demangle, - # we use c++filt instead, if it exists on this system. - my @nm_commands = (ShellEscape($nm, "-n", $flatten_flag, $demangle_flag, - $image) . " 2>$dev_null $cppfilt_flag", - ShellEscape($nm, "-D", "-n", $flatten_flag, $demangle_flag, - $image) . " 2>$dev_null $cppfilt_flag", - # 6nm is for Go binaries - ShellEscape("6nm", "$image") . " 2>$dev_null | sort", - ); - - # If the executable is an MS Windows PDB-format executable, we'll - # have set up obj_tool_map("nm_pdb"). In this case, we actually - # want to use both unix nm and windows-specific nm_pdb, since - # PDB-format executables can apparently include dwarf .o files. - if (exists $obj_tool_map{"nm_pdb"}) { - push(@nm_commands, - ShellEscape($obj_tool_map{"nm_pdb"}, "--demangle", $image) - . " 2>$dev_null"); - } - - foreach my $nm_command (@nm_commands) { - my $symbol_table = GetProcedureBoundariesViaNm($nm_command, $regexp); - return $symbol_table if (%{$symbol_table}); - } - my $symbol_table = {}; - return $symbol_table; -} - - -# The test vectors for AddressAdd/Sub/Inc are 8-16-nibble hex strings. -# To make them more readable, we add underscores at interesting places. -# This routine removes the underscores, producing the canonical representation -# used by jeprof to represent addresses, particularly in the tested routines. -sub CanonicalHex { - my $arg = shift; - return join '', (split '_',$arg); -} - - -# Unit test for AddressAdd: -sub AddressAddUnitTest { - my $test_data_8 = shift; - my $test_data_16 = shift; - my $error_count = 0; - my $fail_count = 0; - my $pass_count = 0; - # print STDERR "AddressAddUnitTest: ", 1+$#{$test_data_8}, " tests\n"; - - # First a few 8-nibble addresses. Note that this implementation uses - # plain old arithmetic, so a quick sanity check along with verifying what - # happens to overflow (we want it to wrap): - $address_length = 8; - foreach my $row (@{$test_data_8}) { - if ($main::opt_debug and $main::opt_test) { print STDERR "@{$row}\n"; } - my $sum = AddressAdd ($row->[0], $row->[1]); - if ($sum ne $row->[2]) { - printf STDERR "ERROR: %s != %s + %s = %s\n", $sum, - $row->[0], $row->[1], $row->[2]; - ++$fail_count; - } else { - ++$pass_count; - } - } - printf STDERR "AddressAdd 32-bit tests: %d passes, %d failures\n", - $pass_count, $fail_count; - $error_count = $fail_count; - $fail_count = 0; - $pass_count = 0; - - # Now 16-nibble addresses. - $address_length = 16; - foreach my $row (@{$test_data_16}) { - if ($main::opt_debug and $main::opt_test) { print STDERR "@{$row}\n"; } - my $sum = AddressAdd (CanonicalHex($row->[0]), CanonicalHex($row->[1])); - my $expected = join '', (split '_',$row->[2]); - if ($sum ne CanonicalHex($row->[2])) { - printf STDERR "ERROR: %s != %s + %s = %s\n", $sum, - $row->[0], $row->[1], $row->[2]; - ++$fail_count; - } else { - ++$pass_count; - } - } - printf STDERR "AddressAdd 64-bit tests: %d passes, %d failures\n", - $pass_count, $fail_count; - $error_count += $fail_count; - - return $error_count; -} - - -# Unit test for AddressSub: -sub AddressSubUnitTest { - my $test_data_8 = shift; - my $test_data_16 = shift; - my $error_count = 0; - my $fail_count = 0; - my $pass_count = 0; - # print STDERR "AddressSubUnitTest: ", 1+$#{$test_data_8}, " tests\n"; - - # First a few 8-nibble addresses. Note that this implementation uses - # plain old arithmetic, so a quick sanity check along with verifying what - # happens to overflow (we want it to wrap): - $address_length = 8; - foreach my $row (@{$test_data_8}) { - if ($main::opt_debug and $main::opt_test) { print STDERR "@{$row}\n"; } - my $sum = AddressSub ($row->[0], $row->[1]); - if ($sum ne $row->[3]) { - printf STDERR "ERROR: %s != %s - %s = %s\n", $sum, - $row->[0], $row->[1], $row->[3]; - ++$fail_count; - } else { - ++$pass_count; - } - } - printf STDERR "AddressSub 32-bit tests: %d passes, %d failures\n", - $pass_count, $fail_count; - $error_count = $fail_count; - $fail_count = 0; - $pass_count = 0; - - # Now 16-nibble addresses. - $address_length = 16; - foreach my $row (@{$test_data_16}) { - if ($main::opt_debug and $main::opt_test) { print STDERR "@{$row}\n"; } - my $sum = AddressSub (CanonicalHex($row->[0]), CanonicalHex($row->[1])); - if ($sum ne CanonicalHex($row->[3])) { - printf STDERR "ERROR: %s != %s - %s = %s\n", $sum, - $row->[0], $row->[1], $row->[3]; - ++$fail_count; - } else { - ++$pass_count; - } - } - printf STDERR "AddressSub 64-bit tests: %d passes, %d failures\n", - $pass_count, $fail_count; - $error_count += $fail_count; - - return $error_count; -} - - -# Unit test for AddressInc: -sub AddressIncUnitTest { - my $test_data_8 = shift; - my $test_data_16 = shift; - my $error_count = 0; - my $fail_count = 0; - my $pass_count = 0; - # print STDERR "AddressIncUnitTest: ", 1+$#{$test_data_8}, " tests\n"; - - # First a few 8-nibble addresses. Note that this implementation uses - # plain old arithmetic, so a quick sanity check along with verifying what - # happens to overflow (we want it to wrap): - $address_length = 8; - foreach my $row (@{$test_data_8}) { - if ($main::opt_debug and $main::opt_test) { print STDERR "@{$row}\n"; } - my $sum = AddressInc ($row->[0]); - if ($sum ne $row->[4]) { - printf STDERR "ERROR: %s != %s + 1 = %s\n", $sum, - $row->[0], $row->[4]; - ++$fail_count; - } else { - ++$pass_count; - } - } - printf STDERR "AddressInc 32-bit tests: %d passes, %d failures\n", - $pass_count, $fail_count; - $error_count = $fail_count; - $fail_count = 0; - $pass_count = 0; - - # Now 16-nibble addresses. - $address_length = 16; - foreach my $row (@{$test_data_16}) { - if ($main::opt_debug and $main::opt_test) { print STDERR "@{$row}\n"; } - my $sum = AddressInc (CanonicalHex($row->[0])); - if ($sum ne CanonicalHex($row->[4])) { - printf STDERR "ERROR: %s != %s + 1 = %s\n", $sum, - $row->[0], $row->[4]; - ++$fail_count; - } else { - ++$pass_count; - } - } - printf STDERR "AddressInc 64-bit tests: %d passes, %d failures\n", - $pass_count, $fail_count; - $error_count += $fail_count; - - return $error_count; -} - - -# Driver for unit tests. -# Currently just the address add/subtract/increment routines for 64-bit. -sub RunUnitTests { - my $error_count = 0; - - # This is a list of tuples [a, b, a+b, a-b, a+1] - my $unit_test_data_8 = [ - [qw(aaaaaaaa 50505050 fafafafa 5a5a5a5a aaaaaaab)], - [qw(50505050 aaaaaaaa fafafafa a5a5a5a6 50505051)], - [qw(ffffffff aaaaaaaa aaaaaaa9 55555555 00000000)], - [qw(00000001 ffffffff 00000000 00000002 00000002)], - [qw(00000001 fffffff0 fffffff1 00000011 00000002)], - ]; - my $unit_test_data_16 = [ - # The implementation handles data in 7-nibble chunks, so those are the - # interesting boundaries. - [qw(aaaaaaaa 50505050 - 00_000000f_afafafa 00_0000005_a5a5a5a 00_000000a_aaaaaab)], - [qw(50505050 aaaaaaaa - 00_000000f_afafafa ff_ffffffa_5a5a5a6 00_0000005_0505051)], - [qw(ffffffff aaaaaaaa - 00_000001a_aaaaaa9 00_0000005_5555555 00_0000010_0000000)], - [qw(00000001 ffffffff - 00_0000010_0000000 ff_ffffff0_0000002 00_0000000_0000002)], - [qw(00000001 fffffff0 - 00_000000f_ffffff1 ff_ffffff0_0000011 00_0000000_0000002)], - - [qw(00_a00000a_aaaaaaa 50505050 - 00_a00000f_afafafa 00_a000005_a5a5a5a 00_a00000a_aaaaaab)], - [qw(0f_fff0005_0505050 aaaaaaaa - 0f_fff000f_afafafa 0f_ffefffa_5a5a5a6 0f_fff0005_0505051)], - [qw(00_000000f_fffffff 01_800000a_aaaaaaa - 01_800001a_aaaaaa9 fe_8000005_5555555 00_0000010_0000000)], - [qw(00_0000000_0000001 ff_fffffff_fffffff - 00_0000000_0000000 00_0000000_0000002 00_0000000_0000002)], - [qw(00_0000000_0000001 ff_fffffff_ffffff0 - ff_fffffff_ffffff1 00_0000000_0000011 00_0000000_0000002)], - ]; - - $error_count += AddressAddUnitTest($unit_test_data_8, $unit_test_data_16); - $error_count += AddressSubUnitTest($unit_test_data_8, $unit_test_data_16); - $error_count += AddressIncUnitTest($unit_test_data_8, $unit_test_data_16); - if ($error_count > 0) { - print STDERR $error_count, " errors: FAILED\n"; - } else { - print STDERR "PASS\n"; - } - exit ($error_count); -} ->>>>>>> main diff --git a/contrib/jemalloc/build-aux/config.guess b/contrib/jemalloc/build-aux/config.guess index e8241c60f184..f7727026b706 100755 --- a/contrib/jemalloc/build-aux/config.guess +++ b/contrib/jemalloc/build-aux/config.guess @@ -1,4 +1,3 @@ -<<<<<<< HEAD #! /bin/sh # Attempt to guess a canonical system name. # Copyright 1992-2021 Free Software Foundation, Inc. @@ -1700,1468 +1699,3 @@ exit 1 # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: -||||||| dec341af7695 -======= -#! /bin/sh -# Attempt to guess a canonical system name. -# Copyright 1992-2016 Free Software Foundation, Inc. - -timestamp='2016-10-02' - -# This file is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, see <http://www.gnu.org/licenses/>. -# -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that -# program. This Exception is an additional permission under section 7 -# of the GNU General Public License, version 3 ("GPLv3"). -# -# Originally written by Per Bothner; maintained since 2000 by Ben Elliston. -# -# You can get the latest version of this script from: -# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess -# -# Please send patches to <config-patches@gnu.org>. - - -me=`echo "$0" | sed -e 's,.*/,,'` - -usage="\ -Usage: $0 [OPTION] - -Output the configuration name of the system \`$me' is run on. - -Operation modes: - -h, --help print this help, then exit - -t, --time-stamp print date of last modification, then exit - -v, --version print version number, then exit - -Report bugs and patches to <config-patches@gnu.org>." - -version="\ -GNU config.guess ($timestamp) - -Originally written by Per Bothner. -Copyright 1992-2016 Free Software Foundation, Inc. - -This is free software; see the source for copying conditions. There is NO -warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." - -help=" -Try \`$me --help' for more information." - -# Parse command line -while test $# -gt 0 ; do - case $1 in - --time-stamp | --time* | -t ) - echo "$timestamp" ; exit ;; - --version | -v ) - echo "$version" ; exit ;; - --help | --h* | -h ) - echo "$usage"; exit ;; - -- ) # Stop option processing - shift; break ;; - - ) # Use stdin as input. - break ;; - -* ) - echo "$me: invalid option $1$help" >&2 - exit 1 ;; - * ) - break ;; - esac -done - -if test $# != 0; then - echo "$me: too many arguments$help" >&2 - exit 1 -fi - -trap 'exit 1' 1 2 15 - -# CC_FOR_BUILD -- compiler used by this script. Note that the use of a -# compiler to aid in system detection is discouraged as it requires -# temporary files to be created and, as you can see below, it is a -# headache to deal with in a portable fashion. - -# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still -# use `HOST_CC' if defined, but it is deprecated. - -# Portable tmp directory creation inspired by the Autoconf team. - -set_cc_for_build=' -trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; -trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; -: ${TMPDIR=/tmp} ; - { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || - { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || - { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || - { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; -dummy=$tmp/dummy ; -tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; -case $CC_FOR_BUILD,$HOST_CC,$CC in - ,,) echo "int x;" > $dummy.c ; - for c in cc gcc c89 c99 ; do - if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then - CC_FOR_BUILD="$c"; break ; - fi ; - done ; - if test x"$CC_FOR_BUILD" = x ; then - CC_FOR_BUILD=no_compiler_found ; - fi - ;; - ,,*) CC_FOR_BUILD=$CC ;; - ,*,*) CC_FOR_BUILD=$HOST_CC ;; -esac ; set_cc_for_build= ;' - -# This is needed to find uname on a Pyramid OSx when run in the BSD universe. -# (ghazi@noc.rutgers.edu 1994-08-24) -if (test -f /.attbin/uname) >/dev/null 2>&1 ; then - PATH=$PATH:/.attbin ; export PATH -fi - -UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown -UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown -UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown -UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown - -case "${UNAME_SYSTEM}" in -Linux|GNU|GNU/*) - # If the system lacks a compiler, then just pick glibc. - # We could probably try harder. - LIBC=gnu - - eval $set_cc_for_build - cat <<-EOF > $dummy.c - #include <features.h> - #if defined(__UCLIBC__) - LIBC=uclibc - #elif defined(__dietlibc__) - LIBC=dietlibc - #else - LIBC=gnu - #endif - EOF - eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC' | sed 's, ,,g'` - ;; -esac - -# Note: order is significant - the case branches are not exclusive. - -case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in - *:NetBSD:*:*) - # NetBSD (nbsd) targets should (where applicable) match one or - # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, - # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently - # switched to ELF, *-*-netbsd* would select the old - # object file format. This provides both forward - # compatibility and a consistent mechanism for selecting the - # object file format. - # - # Note: NetBSD doesn't particularly care about the vendor - # portion of the name. We always set it to "unknown". - sysctl="sysctl -n hw.machine_arch" - UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \ - /sbin/$sysctl 2>/dev/null || \ - /usr/sbin/$sysctl 2>/dev/null || \ - echo unknown)` - case "${UNAME_MACHINE_ARCH}" in - armeb) machine=armeb-unknown ;; - arm*) machine=arm-unknown ;; - sh3el) machine=shl-unknown ;; - sh3eb) machine=sh-unknown ;; - sh5el) machine=sh5le-unknown ;; - earmv*) - arch=`echo ${UNAME_MACHINE_ARCH} | sed -e 's,^e\(armv[0-9]\).*$,\1,'` - endian=`echo ${UNAME_MACHINE_ARCH} | sed -ne 's,^.*\(eb\)$,\1,p'` - machine=${arch}${endian}-unknown - ;; - *) machine=${UNAME_MACHINE_ARCH}-unknown ;; - esac - # The Operating System including object format, if it has switched - # to ELF recently (or will in the future) and ABI. - case "${UNAME_MACHINE_ARCH}" in - earm*) - os=netbsdelf - ;; - arm*|i386|m68k|ns32k|sh3*|sparc|vax) - eval $set_cc_for_build - if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ - | grep -q __ELF__ - then - # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). - # Return netbsd for either. FIX? - os=netbsd - else - os=netbsdelf - fi - ;; - *) - os=netbsd - ;; - esac - # Determine ABI tags. - case "${UNAME_MACHINE_ARCH}" in - earm*) - expr='s/^earmv[0-9]/-eabi/;s/eb$//' - abi=`echo ${UNAME_MACHINE_ARCH} | sed -e "$expr"` - ;; - esac - # The OS release - # Debian GNU/NetBSD machines have a different userland, and - # thus, need a distinct triplet. However, they do not need - # kernel version information, so it can be replaced with a - # suitable tag, in the style of linux-gnu. - case "${UNAME_VERSION}" in - Debian*) - release='-gnu' - ;; - *) - release=`echo ${UNAME_RELEASE} | sed -e 's/[-_].*//' | cut -d. -f1,2` - ;; - esac - # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: - # contains redundant information, the shorter form: - # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. - echo "${machine}-${os}${release}${abi}" - exit ;; - *:Bitrig:*:*) - UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` - echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE} - exit ;; - *:OpenBSD:*:*) - UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` - echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} - exit ;; - *:LibertyBSD:*:*) - UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'` - echo ${UNAME_MACHINE_ARCH}-unknown-libertybsd${UNAME_RELEASE} - exit ;; - *:ekkoBSD:*:*) - echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} - exit ;; - *:SolidBSD:*:*) - echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} - exit ;; - macppc:MirBSD:*:*) - echo powerpc-unknown-mirbsd${UNAME_RELEASE} - exit ;; - *:MirBSD:*:*) - echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} - exit ;; - *:Sortix:*:*) - echo ${UNAME_MACHINE}-unknown-sortix - exit ;; - alpha:OSF1:*:*) - case $UNAME_RELEASE in - *4.0) - UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` - ;; - *5.*) - UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` - ;; - esac - # According to Compaq, /usr/sbin/psrinfo has been available on - # OSF/1 and Tru64 systems produced since 1995. I hope that - # covers most systems running today. This code pipes the CPU - # types through head -n 1, so we only detect the type of CPU 0. - ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` - case "$ALPHA_CPU_TYPE" in - "EV4 (21064)") - UNAME_MACHINE=alpha ;; - "EV4.5 (21064)") - UNAME_MACHINE=alpha ;; - "LCA4 (21066/21068)") - UNAME_MACHINE=alpha ;; - "EV5 (21164)") - UNAME_MACHINE=alphaev5 ;; - "EV5.6 (21164A)") - UNAME_MACHINE=alphaev56 ;; - "EV5.6 (21164PC)") - UNAME_MACHINE=alphapca56 ;; - "EV5.7 (21164PC)") - UNAME_MACHINE=alphapca57 ;; - "EV6 (21264)") - UNAME_MACHINE=alphaev6 ;; - "EV6.7 (21264A)") - UNAME_MACHINE=alphaev67 ;; - "EV6.8CB (21264C)") - UNAME_MACHINE=alphaev68 ;; - "EV6.8AL (21264B)") - UNAME_MACHINE=alphaev68 ;; - "EV6.8CX (21264D)") - UNAME_MACHINE=alphaev68 ;; - "EV6.9A (21264/EV69A)") - UNAME_MACHINE=alphaev69 ;; - "EV7 (21364)") - UNAME_MACHINE=alphaev7 ;; - "EV7.9 (21364A)") - UNAME_MACHINE=alphaev79 ;; - esac - # A Pn.n version is a patched version. - # A Vn.n version is a released version. - # A Tn.n version is a released field test version. - # A Xn.n version is an unreleased experimental baselevel. - # 1.2 uses "1.2" for uname -r. - echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` - # Reset EXIT trap before exiting to avoid spurious non-zero exit code. - exitcode=$? - trap '' 0 - exit $exitcode ;; - Alpha\ *:Windows_NT*:*) - # How do we know it's Interix rather than the generic POSIX subsystem? - # Should we change UNAME_MACHINE based on the output of uname instead - # of the specific Alpha model? - echo alpha-pc-interix - exit ;; - 21064:Windows_NT:50:3) - echo alpha-dec-winnt3.5 - exit ;; - Amiga*:UNIX_System_V:4.0:*) - echo m68k-unknown-sysv4 - exit ;; - *:[Aa]miga[Oo][Ss]:*:*) - echo ${UNAME_MACHINE}-unknown-amigaos - exit ;; - *:[Mm]orph[Oo][Ss]:*:*) - echo ${UNAME_MACHINE}-unknown-morphos - exit ;; - *:OS/390:*:*) - echo i370-ibm-openedition - exit ;; - *:z/VM:*:*) - echo s390-ibm-zvmoe - exit ;; - *:OS400:*:*) - echo powerpc-ibm-os400 - exit ;; - arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) - echo arm-acorn-riscix${UNAME_RELEASE} - exit ;; - arm*:riscos:*:*|arm*:RISCOS:*:*) - echo arm-unknown-riscos - exit ;; - SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) - echo hppa1.1-hitachi-hiuxmpp - exit ;; - Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) - # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. - if test "`(/bin/universe) 2>/dev/null`" = att ; then - echo pyramid-pyramid-sysv3 - else - echo pyramid-pyramid-bsd - fi - exit ;; - NILE*:*:*:dcosx) - echo pyramid-pyramid-svr4 - exit ;; - DRS?6000:unix:4.0:6*) - echo sparc-icl-nx6 - exit ;; - DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) - case `/usr/bin/uname -p` in - sparc) echo sparc-icl-nx7; exit ;; - esac ;; - s390x:SunOS:*:*) - echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - sun4H:SunOS:5.*:*) - echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) - echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) - echo i386-pc-auroraux${UNAME_RELEASE} - exit ;; - i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) - eval $set_cc_for_build - SUN_ARCH=i386 - # If there is a compiler, see if it is configured for 64-bit objects. - # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. - # This test works for both compilers. - if [ "$CC_FOR_BUILD" != no_compiler_found ]; then - if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ - (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ - grep IS_64BIT_ARCH >/dev/null - then - SUN_ARCH=x86_64 - fi - fi - echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - sun4*:SunOS:6*:*) - # According to config.sub, this is the proper way to canonicalize - # SunOS6. Hard to guess exactly what SunOS6 will be like, but - # it's likely to be more like Solaris than SunOS4. - echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - sun4*:SunOS:*:*) - case "`/usr/bin/arch -k`" in - Series*|S4*) - UNAME_RELEASE=`uname -v` - ;; - esac - # Japanese Language versions have a version number like `4.1.3-JL'. - echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` - exit ;; - sun3*:SunOS:*:*) - echo m68k-sun-sunos${UNAME_RELEASE} - exit ;; - sun*:*:4.2BSD:*) - UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` - test "x${UNAME_RELEASE}" = x && UNAME_RELEASE=3 - case "`/bin/arch`" in - sun3) - echo m68k-sun-sunos${UNAME_RELEASE} - ;; - sun4) - echo sparc-sun-sunos${UNAME_RELEASE} - ;; - esac - exit ;; - aushp:SunOS:*:*) - echo sparc-auspex-sunos${UNAME_RELEASE} - exit ;; - # The situation for MiNT is a little confusing. The machine name - # can be virtually everything (everything which is not - # "atarist" or "atariste" at least should have a processor - # > m68000). The system name ranges from "MiNT" over "FreeMiNT" - # to the lowercase version "mint" (or "freemint"). Finally - # the system name "TOS" denotes a system which is actually not - # MiNT. But MiNT is downward compatible to TOS, so this should - # be no problem. - atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} - exit ;; - atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} - exit ;; - *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} - exit ;; - milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) - echo m68k-milan-mint${UNAME_RELEASE} - exit ;; - hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) - echo m68k-hades-mint${UNAME_RELEASE} - exit ;; - *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) - echo m68k-unknown-mint${UNAME_RELEASE} - exit ;; - m68k:machten:*:*) - echo m68k-apple-machten${UNAME_RELEASE} - exit ;; - powerpc:machten:*:*) - echo powerpc-apple-machten${UNAME_RELEASE} - exit ;; - RISC*:Mach:*:*) - echo mips-dec-mach_bsd4.3 - exit ;; - RISC*:ULTRIX:*:*) - echo mips-dec-ultrix${UNAME_RELEASE} - exit ;; - VAX*:ULTRIX*:*:*) - echo vax-dec-ultrix${UNAME_RELEASE} - exit ;; - 2020:CLIX:*:* | 2430:CLIX:*:*) - echo clipper-intergraph-clix${UNAME_RELEASE} - exit ;; - mips:*:*:UMIPS | mips:*:*:RISCos) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c -#ifdef __cplusplus -#include <stdio.h> /* for printf() prototype */ - int main (int argc, char *argv[]) { -#else - int main (argc, argv) int argc; char *argv[]; { -#endif - #if defined (host_mips) && defined (MIPSEB) - #if defined (SYSTYPE_SYSV) - printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); - #endif - #if defined (SYSTYPE_SVR4) - printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); - #endif - #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) - printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); - #endif - #endif - exit (-1); - } -EOF - $CC_FOR_BUILD -o $dummy $dummy.c && - dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && - SYSTEM_NAME=`$dummy $dummyarg` && - { echo "$SYSTEM_NAME"; exit; } - echo mips-mips-riscos${UNAME_RELEASE} - exit ;; - Motorola:PowerMAX_OS:*:*) - echo powerpc-motorola-powermax - exit ;; - Motorola:*:4.3:PL8-*) - echo powerpc-harris-powermax - exit ;; - Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) - echo powerpc-harris-powermax - exit ;; - Night_Hawk:Power_UNIX:*:*) - echo powerpc-harris-powerunix - exit ;; - m88k:CX/UX:7*:*) - echo m88k-harris-cxux7 - exit ;; - m88k:*:4*:R4*) - echo m88k-motorola-sysv4 - exit ;; - m88k:*:3*:R3*) - echo m88k-motorola-sysv3 - exit ;; - AViiON:dgux:*:*) - # DG/UX returns AViiON for all architectures - UNAME_PROCESSOR=`/usr/bin/uname -p` - if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] - then - if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ - [ ${TARGET_BINARY_INTERFACE}x = x ] - then - echo m88k-dg-dgux${UNAME_RELEASE} - else - echo m88k-dg-dguxbcs${UNAME_RELEASE} - fi - else - echo i586-dg-dgux${UNAME_RELEASE} - fi - exit ;; - M88*:DolphinOS:*:*) # DolphinOS (SVR3) - echo m88k-dolphin-sysv3 - exit ;; - M88*:*:R3*:*) - # Delta 88k system running SVR3 - echo m88k-motorola-sysv3 - exit ;; - XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) - echo m88k-tektronix-sysv3 - exit ;; - Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) - echo m68k-tektronix-bsd - exit ;; - *:IRIX*:*:*) - echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` - exit ;; - ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. - echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id - exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' - i*86:AIX:*:*) - echo i386-ibm-aix - exit ;; - ia64:AIX:*:*) - if [ -x /usr/bin/oslevel ] ; then - IBM_REV=`/usr/bin/oslevel` - else - IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} - fi - echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} - exit ;; - *:AIX:2:3) - if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #include <sys/systemcfg.h> - - main() - { - if (!__power_pc()) - exit(1); - puts("powerpc-ibm-aix3.2.5"); - exit(0); - } -EOF - if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` - then - echo "$SYSTEM_NAME" - else - echo rs6000-ibm-aix3.2.5 - fi - elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then - echo rs6000-ibm-aix3.2.4 - else - echo rs6000-ibm-aix3.2 - fi - exit ;; - *:AIX:*:[4567]) - IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` - if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then - IBM_ARCH=rs6000 - else - IBM_ARCH=powerpc - fi - if [ -x /usr/bin/lslpp ] ; then - IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc | - awk -F: '{ print $3 }' | sed s/[0-9]*$/0/` - else - IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} - fi - echo ${IBM_ARCH}-ibm-aix${IBM_REV} - exit ;; - *:AIX:*:*) - echo rs6000-ibm-aix - exit ;; - ibmrt:4.4BSD:*|romp-ibm:BSD:*) - echo romp-ibm-bsd4.4 - exit ;; - ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and - echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to - exit ;; # report: romp-ibm BSD 4.3 - *:BOSX:*:*) - echo rs6000-bull-bosx - exit ;; - DPX/2?00:B.O.S.:*:*) - echo m68k-bull-sysv3 - exit ;; - 9000/[34]??:4.3bsd:1.*:*) - echo m68k-hp-bsd - exit ;; - hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) - echo m68k-hp-bsd4.4 - exit ;; - 9000/[34678]??:HP-UX:*:*) - HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` - case "${UNAME_MACHINE}" in - 9000/31? ) HP_ARCH=m68000 ;; - 9000/[34]?? ) HP_ARCH=m68k ;; - 9000/[678][0-9][0-9]) - if [ -x /usr/bin/getconf ]; then - sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` - sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` - case "${sc_cpu_version}" in - 523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0 - 528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1 - 532) # CPU_PA_RISC2_0 - case "${sc_kernel_bits}" in - 32) HP_ARCH=hppa2.0n ;; - 64) HP_ARCH=hppa2.0w ;; - '') HP_ARCH=hppa2.0 ;; # HP-UX 10.20 - esac ;; - esac - fi - if [ "${HP_ARCH}" = "" ]; then - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - - #define _HPUX_SOURCE - #include <stdlib.h> - #include <unistd.h> - - int main () - { - #if defined(_SC_KERNEL_BITS) - long bits = sysconf(_SC_KERNEL_BITS); - #endif - long cpu = sysconf (_SC_CPU_VERSION); - - switch (cpu) - { - case CPU_PA_RISC1_0: puts ("hppa1.0"); break; - case CPU_PA_RISC1_1: puts ("hppa1.1"); break; - case CPU_PA_RISC2_0: - #if defined(_SC_KERNEL_BITS) - switch (bits) - { - case 64: puts ("hppa2.0w"); break; - case 32: puts ("hppa2.0n"); break; - default: puts ("hppa2.0"); break; - } break; - #else /* !defined(_SC_KERNEL_BITS) */ - puts ("hppa2.0"); break; - #endif - default: puts ("hppa1.0"); break; - } - exit (0); - } -EOF - (CCOPTS="" $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` - test -z "$HP_ARCH" && HP_ARCH=hppa - fi ;; - esac - if [ ${HP_ARCH} = hppa2.0w ] - then - eval $set_cc_for_build - - # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating - # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler - # generating 64-bit code. GNU and HP use different nomenclature: - # - # $ CC_FOR_BUILD=cc ./config.guess - # => hppa2.0w-hp-hpux11.23 - # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess - # => hppa64-hp-hpux11.23 - - if echo __LP64__ | (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | - grep -q __LP64__ - then - HP_ARCH=hppa2.0w - else - HP_ARCH=hppa64 - fi - fi - echo ${HP_ARCH}-hp-hpux${HPUX_REV} - exit ;; - ia64:HP-UX:*:*) - HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` - echo ia64-hp-hpux${HPUX_REV} - exit ;; - 3050*:HI-UX:*:*) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #include <unistd.h> - int - main () - { - long cpu = sysconf (_SC_CPU_VERSION); - /* The order matters, because CPU_IS_HP_MC68K erroneously returns - true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct - results, however. */ - if (CPU_IS_PA_RISC (cpu)) - { - switch (cpu) - { - case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; - case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; - case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; - default: puts ("hppa-hitachi-hiuxwe2"); break; - } - } - else if (CPU_IS_HP_MC68K (cpu)) - puts ("m68k-hitachi-hiuxwe2"); - else puts ("unknown-hitachi-hiuxwe2"); - exit (0); - } -EOF - $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && - { echo "$SYSTEM_NAME"; exit; } - echo unknown-hitachi-hiuxwe2 - exit ;; - 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) - echo hppa1.1-hp-bsd - exit ;; - 9000/8??:4.3bsd:*:*) - echo hppa1.0-hp-bsd - exit ;; - *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) - echo hppa1.0-hp-mpeix - exit ;; - hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) - echo hppa1.1-hp-osf - exit ;; - hp8??:OSF1:*:*) - echo hppa1.0-hp-osf - exit ;; - i*86:OSF1:*:*) - if [ -x /usr/sbin/sysversion ] ; then - echo ${UNAME_MACHINE}-unknown-osf1mk - else - echo ${UNAME_MACHINE}-unknown-osf1 - fi - exit ;; - parisc*:Lites*:*:*) - echo hppa1.1-hp-lites - exit ;; - C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) - echo c1-convex-bsd - exit ;; - C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) - if getsysinfo -f scalar_acc - then echo c32-convex-bsd - else echo c2-convex-bsd - fi - exit ;; - C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) - echo c34-convex-bsd - exit ;; - C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) - echo c38-convex-bsd - exit ;; - C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) - echo c4-convex-bsd - exit ;; - CRAY*Y-MP:*:*:*) - echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit ;; - CRAY*[A-Z]90:*:*:*) - echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ - | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ - -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ - -e 's/\.[^.]*$/.X/' - exit ;; - CRAY*TS:*:*:*) - echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit ;; - CRAY*T3E:*:*:*) - echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit ;; - CRAY*SV1:*:*:*) - echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit ;; - *:UNICOS/mp:*:*) - echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit ;; - F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) - FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` - FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` - FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` - echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" - exit ;; - 5000:UNIX_System_V:4.*:*) - FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` - FUJITSU_REL=`echo ${UNAME_RELEASE} | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'` - echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" - exit ;; - i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) - echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} - exit ;; - sparc*:BSD/OS:*:*) - echo sparc-unknown-bsdi${UNAME_RELEASE} - exit ;; - *:BSD/OS:*:*) - echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} - exit ;; - *:FreeBSD:*:*) - UNAME_PROCESSOR=`/usr/bin/uname -p` - case ${UNAME_PROCESSOR} in - amd64) - echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; - *) - echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; - esac - exit ;; - i*:CYGWIN*:*) - echo ${UNAME_MACHINE}-pc-cygwin - exit ;; - *:MINGW64*:*) - echo ${UNAME_MACHINE}-pc-mingw64 - exit ;; - *:MINGW*:*) - echo ${UNAME_MACHINE}-pc-mingw32 - exit ;; - *:MSYS*:*) - echo ${UNAME_MACHINE}-pc-msys - exit ;; - i*:windows32*:*) - # uname -m includes "-pc" on this system. - echo ${UNAME_MACHINE}-mingw32 - exit ;; - i*:PW*:*) - echo ${UNAME_MACHINE}-pc-pw32 - exit ;; - *:Interix*:*) - case ${UNAME_MACHINE} in - x86) - echo i586-pc-interix${UNAME_RELEASE} - exit ;; - authenticamd | genuineintel | EM64T) - echo x86_64-unknown-interix${UNAME_RELEASE} - exit ;; - IA64) - echo ia64-unknown-interix${UNAME_RELEASE} - exit ;; - esac ;; - [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) - echo i${UNAME_MACHINE}-pc-mks - exit ;; - 8664:Windows_NT:*) - echo x86_64-pc-mks - exit ;; - i*:Windows_NT*:* | Pentium*:Windows_NT*:*) - # How do we know it's Interix rather than the generic POSIX subsystem? - # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we - # UNAME_MACHINE based on the output of uname instead of i386? - echo i586-pc-interix - exit ;; - i*:UWIN*:*) - echo ${UNAME_MACHINE}-pc-uwin - exit ;; - amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) - echo x86_64-unknown-cygwin - exit ;; - p*:CYGWIN*:*) - echo powerpcle-unknown-cygwin - exit ;; - prep*:SunOS:5.*:*) - echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - *:GNU:*:*) - # the GNU system - echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` - exit ;; - *:GNU/*:*:*) - # other systems with GNU libc and userland - echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC} - exit ;; - i*86:Minix:*:*) - echo ${UNAME_MACHINE}-pc-minix - exit ;; - aarch64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - aarch64_be:Linux:*:*) - UNAME_MACHINE=aarch64_be - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - alpha:Linux:*:*) - case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in - EV5) UNAME_MACHINE=alphaev5 ;; - EV56) UNAME_MACHINE=alphaev56 ;; - PCA56) UNAME_MACHINE=alphapca56 ;; - PCA57) UNAME_MACHINE=alphapca56 ;; - EV6) UNAME_MACHINE=alphaev6 ;; - EV67) UNAME_MACHINE=alphaev67 ;; - EV68*) UNAME_MACHINE=alphaev68 ;; - esac - objdump --private-headers /bin/sh | grep -q ld.so.1 - if test "$?" = 0 ; then LIBC=gnulibc1 ; fi - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - arc:Linux:*:* | arceb:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - arm*:Linux:*:*) - eval $set_cc_for_build - if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ - | grep -q __ARM_EABI__ - then - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - else - if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ - | grep -q __ARM_PCS_VFP - then - echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi - else - echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf - fi - fi - exit ;; - avr32*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - cris:Linux:*:*) - echo ${UNAME_MACHINE}-axis-linux-${LIBC} - exit ;; - crisv32:Linux:*:*) - echo ${UNAME_MACHINE}-axis-linux-${LIBC} - exit ;; - e2k:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - frv:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - hexagon:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - i*86:Linux:*:*) - echo ${UNAME_MACHINE}-pc-linux-${LIBC} - exit ;; - ia64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - k1om:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - m32r*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - m68*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - mips:Linux:*:* | mips64:Linux:*:*) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #undef CPU - #undef ${UNAME_MACHINE} - #undef ${UNAME_MACHINE}el - #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) - CPU=${UNAME_MACHINE}el - #else - #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) - CPU=${UNAME_MACHINE} - #else - CPU= - #endif - #endif -EOF - eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` - test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; } - ;; - mips64el:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - openrisc*:Linux:*:*) - echo or1k-unknown-linux-${LIBC} - exit ;; - or32:Linux:*:* | or1k*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - padre:Linux:*:*) - echo sparc-unknown-linux-${LIBC} - exit ;; - parisc64:Linux:*:* | hppa64:Linux:*:*) - echo hppa64-unknown-linux-${LIBC} - exit ;; - parisc:Linux:*:* | hppa:Linux:*:*) - # Look for CPU level - case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in - PA7*) echo hppa1.1-unknown-linux-${LIBC} ;; - PA8*) echo hppa2.0-unknown-linux-${LIBC} ;; - *) echo hppa-unknown-linux-${LIBC} ;; - esac - exit ;; - ppc64:Linux:*:*) - echo powerpc64-unknown-linux-${LIBC} - exit ;; - ppc:Linux:*:*) - echo powerpc-unknown-linux-${LIBC} - exit ;; - ppc64le:Linux:*:*) - echo powerpc64le-unknown-linux-${LIBC} - exit ;; - ppcle:Linux:*:*) - echo powerpcle-unknown-linux-${LIBC} - exit ;; - riscv32:Linux:*:* | riscv64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - s390:Linux:*:* | s390x:Linux:*:*) - echo ${UNAME_MACHINE}-ibm-linux-${LIBC} - exit ;; - sh64*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - sh*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - sparc:Linux:*:* | sparc64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - tile*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - vax:Linux:*:*) - echo ${UNAME_MACHINE}-dec-linux-${LIBC} - exit ;; - x86_64:Linux:*:*) - echo ${UNAME_MACHINE}-pc-linux-${LIBC} - exit ;; - xtensa*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - i*86:DYNIX/ptx:4*:*) - # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. - # earlier versions are messed up and put the nodename in both - # sysname and nodename. - echo i386-sequent-sysv4 - exit ;; - i*86:UNIX_SV:4.2MP:2.*) - # Unixware is an offshoot of SVR4, but it has its own version - # number series starting with 2... - # I am not positive that other SVR4 systems won't match this, - # I just have to hope. -- rms. - # Use sysv4.2uw... so that sysv4* matches it. - echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} - exit ;; - i*86:OS/2:*:*) - # If we were able to find `uname', then EMX Unix compatibility - # is probably installed. - echo ${UNAME_MACHINE}-pc-os2-emx - exit ;; - i*86:XTS-300:*:STOP) - echo ${UNAME_MACHINE}-unknown-stop - exit ;; - i*86:atheos:*:*) - echo ${UNAME_MACHINE}-unknown-atheos - exit ;; - i*86:syllable:*:*) - echo ${UNAME_MACHINE}-pc-syllable - exit ;; - i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) - echo i386-unknown-lynxos${UNAME_RELEASE} - exit ;; - i*86:*DOS:*:*) - echo ${UNAME_MACHINE}-pc-msdosdjgpp - exit ;; - i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) - UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` - if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then - echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} - else - echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} - fi - exit ;; - i*86:*:5:[678]*) - # UnixWare 7.x, OpenUNIX and OpenServer 6. - case `/bin/uname -X | grep "^Machine"` in - *486*) UNAME_MACHINE=i486 ;; - *Pentium) UNAME_MACHINE=i586 ;; - *Pent*|*Celeron) UNAME_MACHINE=i686 ;; - esac - echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} - exit ;; - i*86:*:3.2:*) - if test -f /usr/options/cb.name; then - UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name` - echo ${UNAME_MACHINE}-pc-isc$UNAME_REL - elif /bin/uname -X 2>/dev/null >/dev/null ; then - UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` - (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 - (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ - && UNAME_MACHINE=i586 - (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ - && UNAME_MACHINE=i686 - (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ - && UNAME_MACHINE=i686 - echo ${UNAME_MACHINE}-pc-sco$UNAME_REL - else - echo ${UNAME_MACHINE}-pc-sysv32 - fi - exit ;; - pc:*:*:*) - # Left here for compatibility: - # uname -m prints for DJGPP always 'pc', but it prints nothing about - # the processor, so we play safe by assuming i586. - # Note: whatever this is, it MUST be the same as what config.sub - # prints for the "djgpp" host, or else GDB configure will decide that - # this is a cross-build. - echo i586-pc-msdosdjgpp - exit ;; - Intel:Mach:3*:*) - echo i386-pc-mach3 - exit ;; - paragon:*:*:*) - echo i860-intel-osf1 - exit ;; - i860:*:4.*:*) # i860-SVR4 - if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then - echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 - else # Add other i860-SVR4 vendors below as they are discovered. - echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 - fi - exit ;; - mini*:CTIX:SYS*5:*) - # "miniframe" - echo m68010-convergent-sysv - exit ;; - mc68k:UNIX:SYSTEM5:3.51m) - echo m68k-convergent-sysv - exit ;; - M680?0:D-NIX:5.3:*) - echo m68k-diab-dnix - exit ;; - M68*:*:R3V[5678]*:*) - test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; - 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) - OS_REL='' - test -r /etc/.relid \ - && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` - /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && { echo i486-ncr-sysv4.3${OS_REL}; exit; } - /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ - && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; - 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) - /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && { echo i486-ncr-sysv4; exit; } ;; - NCR*:*:4.2:* | MPRAS*:*:4.2:*) - OS_REL='.3' - test -r /etc/.relid \ - && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` - /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && { echo i486-ncr-sysv4.3${OS_REL}; exit; } - /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ - && { echo i586-ncr-sysv4.3${OS_REL}; exit; } - /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ - && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; - m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) - echo m68k-unknown-lynxos${UNAME_RELEASE} - exit ;; - mc68030:UNIX_System_V:4.*:*) - echo m68k-atari-sysv4 - exit ;; - TSUNAMI:LynxOS:2.*:*) - echo sparc-unknown-lynxos${UNAME_RELEASE} - exit ;; - rs6000:LynxOS:2.*:*) - echo rs6000-unknown-lynxos${UNAME_RELEASE} - exit ;; - PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) - echo powerpc-unknown-lynxos${UNAME_RELEASE} - exit ;; - SM[BE]S:UNIX_SV:*:*) - echo mips-dde-sysv${UNAME_RELEASE} - exit ;; - RM*:ReliantUNIX-*:*:*) - echo mips-sni-sysv4 - exit ;; - RM*:SINIX-*:*:*) - echo mips-sni-sysv4 - exit ;; - *:SINIX-*:*:*) - if uname -p 2>/dev/null >/dev/null ; then - UNAME_MACHINE=`(uname -p) 2>/dev/null` - echo ${UNAME_MACHINE}-sni-sysv4 - else - echo ns32k-sni-sysv - fi - exit ;; - PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort - # says <Richard.M.Bartel@ccMail.Census.GOV> - echo i586-unisys-sysv4 - exit ;; - *:UNIX_System_V:4*:FTX*) - # From Gerald Hewes <hewes@openmarket.com>. - # How about differentiating between stratus architectures? -djm - echo hppa1.1-stratus-sysv4 - exit ;; - *:*:*:FTX*) - # From seanf@swdc.stratus.com. - echo i860-stratus-sysv4 - exit ;; - i*86:VOS:*:*) - # From Paul.Green@stratus.com. - echo ${UNAME_MACHINE}-stratus-vos - exit ;; - *:VOS:*:*) - # From Paul.Green@stratus.com. - echo hppa1.1-stratus-vos - exit ;; - mc68*:A/UX:*:*) - echo m68k-apple-aux${UNAME_RELEASE} - exit ;; - news*:NEWS-OS:6*:*) - echo mips-sony-newsos6 - exit ;; - R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) - if [ -d /usr/nec ]; then - echo mips-nec-sysv${UNAME_RELEASE} - else - echo mips-unknown-sysv${UNAME_RELEASE} - fi - exit ;; - BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. - echo powerpc-be-beos - exit ;; - BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. - echo powerpc-apple-beos - exit ;; - BePC:BeOS:*:*) # BeOS running on Intel PC compatible. - echo i586-pc-beos - exit ;; - BePC:Haiku:*:*) # Haiku running on Intel PC compatible. - echo i586-pc-haiku - exit ;; - x86_64:Haiku:*:*) - echo x86_64-unknown-haiku - exit ;; - SX-4:SUPER-UX:*:*) - echo sx4-nec-superux${UNAME_RELEASE} - exit ;; - SX-5:SUPER-UX:*:*) - echo sx5-nec-superux${UNAME_RELEASE} - exit ;; - SX-6:SUPER-UX:*:*) - echo sx6-nec-superux${UNAME_RELEASE} - exit ;; - SX-7:SUPER-UX:*:*) - echo sx7-nec-superux${UNAME_RELEASE} - exit ;; - SX-8:SUPER-UX:*:*) - echo sx8-nec-superux${UNAME_RELEASE} - exit ;; - SX-8R:SUPER-UX:*:*) - echo sx8r-nec-superux${UNAME_RELEASE} - exit ;; - SX-ACE:SUPER-UX:*:*) - echo sxace-nec-superux${UNAME_RELEASE} - exit ;; - Power*:Rhapsody:*:*) - echo powerpc-apple-rhapsody${UNAME_RELEASE} - exit ;; - *:Rhapsody:*:*) - echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} - exit ;; - *:Darwin:*:*) - UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown - eval $set_cc_for_build - if test "$UNAME_PROCESSOR" = unknown ; then - UNAME_PROCESSOR=powerpc - fi - if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then - if [ "$CC_FOR_BUILD" != no_compiler_found ]; then - if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ - (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ - grep IS_64BIT_ARCH >/dev/null - then - case $UNAME_PROCESSOR in - i386) UNAME_PROCESSOR=x86_64 ;; - powerpc) UNAME_PROCESSOR=powerpc64 ;; - esac - fi - fi - elif test "$UNAME_PROCESSOR" = i386 ; then - # Avoid executing cc on OS X 10.9, as it ships with a stub - # that puts up a graphical alert prompting to install - # developer tools. Any system running Mac OS X 10.7 or - # later (Darwin 11 and later) is required to have a 64-bit - # processor. This is not true of the ARM version of Darwin - # that Apple uses in portable devices. - UNAME_PROCESSOR=x86_64 - fi - echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} - exit ;; - *:procnto*:*:* | *:QNX:[0123456789]*:*) - UNAME_PROCESSOR=`uname -p` - if test "$UNAME_PROCESSOR" = x86; then - UNAME_PROCESSOR=i386 - UNAME_MACHINE=pc - fi - echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} - exit ;; - *:QNX:*:4*) - echo i386-pc-qnx - exit ;; - NEO-?:NONSTOP_KERNEL:*:*) - echo neo-tandem-nsk${UNAME_RELEASE} - exit ;; - NSE-*:NONSTOP_KERNEL:*:*) - echo nse-tandem-nsk${UNAME_RELEASE} - exit ;; - NSR-?:NONSTOP_KERNEL:*:*) - echo nsr-tandem-nsk${UNAME_RELEASE} - exit ;; - *:NonStop-UX:*:*) - echo mips-compaq-nonstopux - exit ;; - BS2000:POSIX*:*:*) - echo bs2000-siemens-sysv - exit ;; - DS/*:UNIX_System_V:*:*) - echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} - exit ;; - *:Plan9:*:*) - # "uname -m" is not consistent, so use $cputype instead. 386 - # is converted to i386 for consistency with other x86 - # operating systems. - if test "$cputype" = 386; then - UNAME_MACHINE=i386 - else - UNAME_MACHINE="$cputype" - fi - echo ${UNAME_MACHINE}-unknown-plan9 - exit ;; - *:TOPS-10:*:*) - echo pdp10-unknown-tops10 - exit ;; - *:TENEX:*:*) - echo pdp10-unknown-tenex - exit ;; - KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) - echo pdp10-dec-tops20 - exit ;; - XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) - echo pdp10-xkl-tops20 - exit ;; - *:TOPS-20:*:*) - echo pdp10-unknown-tops20 - exit ;; - *:ITS:*:*) - echo pdp10-unknown-its - exit ;; - SEI:*:*:SEIUX) - echo mips-sei-seiux${UNAME_RELEASE} - exit ;; - *:DragonFly:*:*) - echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` - exit ;; - *:*VMS:*:*) - UNAME_MACHINE=`(uname -p) 2>/dev/null` - case "${UNAME_MACHINE}" in - A*) echo alpha-dec-vms ; exit ;; - I*) echo ia64-dec-vms ; exit ;; - V*) echo vax-dec-vms ; exit ;; - esac ;; - *:XENIX:*:SysV) - echo i386-pc-xenix - exit ;; - i*86:skyos:*:*) - echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE} | sed -e 's/ .*$//'` - exit ;; - i*86:rdos:*:*) - echo ${UNAME_MACHINE}-pc-rdos - exit ;; - i*86:AROS:*:*) - echo ${UNAME_MACHINE}-pc-aros - exit ;; - x86_64:VMkernel:*:*) - echo ${UNAME_MACHINE}-unknown-esx - exit ;; - amd64:Isilon\ OneFS:*:*) - echo x86_64-unknown-onefs - exit ;; -esac - -cat >&2 <<EOF -$0: unable to guess system type - -This script (version $timestamp), has failed to recognize the -operating system you are using. If your script is old, overwrite -config.guess and config.sub with the latest versions from: - - http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess -and - http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub - -If $0 has already been updated, send the following data and any -information you think might be pertinent to config-patches@gnu.org to -provide the necessary information to handle your system. - -config.guess timestamp = $timestamp - -uname -m = `(uname -m) 2>/dev/null || echo unknown` -uname -r = `(uname -r) 2>/dev/null || echo unknown` -uname -s = `(uname -s) 2>/dev/null || echo unknown` -uname -v = `(uname -v) 2>/dev/null || echo unknown` - -/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` -/bin/uname -X = `(/bin/uname -X) 2>/dev/null` - -hostinfo = `(hostinfo) 2>/dev/null` -/bin/universe = `(/bin/universe) 2>/dev/null` -/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` -/bin/arch = `(/bin/arch) 2>/dev/null` -/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` -/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` - -UNAME_MACHINE = ${UNAME_MACHINE} -UNAME_RELEASE = ${UNAME_RELEASE} -UNAME_SYSTEM = ${UNAME_SYSTEM} -UNAME_VERSION = ${UNAME_VERSION} -EOF - -exit 1 - -# Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "timestamp='" -# time-stamp-format: "%:y-%02m-%02d" -# time-stamp-end: "'" -# End: ->>>>>>> main diff --git a/contrib/jemalloc/build-aux/config.sub b/contrib/jemalloc/build-aux/config.sub index 099dab005a9a..b0f8492348d7 100755 --- a/contrib/jemalloc/build-aux/config.sub +++ b/contrib/jemalloc/build-aux/config.sub @@ -1,4 +1,3 @@ -<<<<<<< HEAD #! /bin/sh # Configuration validation subroutine script. # Copyright 1992-2021 Free Software Foundation, Inc. @@ -1854,1831 +1853,3 @@ exit # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: -||||||| dec341af7695 -======= -#! /bin/sh -# Configuration validation subroutine script. -# Copyright 1992-2016 Free Software Foundation, Inc. - -timestamp='2016-11-04' - -# This file is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, see <http://www.gnu.org/licenses/>. -# -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that -# program. This Exception is an additional permission under section 7 -# of the GNU General Public License, version 3 ("GPLv3"). - - -# Please send patches to <config-patches@gnu.org>. -# -# Configuration subroutine to validate and canonicalize a configuration type. -# Supply the specified configuration type as an argument. -# If it is invalid, we print an error message on stderr and exit with code 1. -# Otherwise, we print the canonical config type on stdout and succeed. - -# You can get the latest version of this script from: -# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub - -# This file is supposed to be the same for all GNU packages -# and recognize all the CPU types, system types and aliases -# that are meaningful with *any* GNU software. -# Each package is responsible for reporting which valid configurations -# it does not support. The user should be able to distinguish -# a failure to support a valid configuration from a meaningless -# configuration. - -# The goal of this file is to map all the various variations of a given -# machine specification into a single specification in the form: -# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM -# or in some cases, the newer four-part form: -# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM -# It is wrong to echo any other type of specification. - -me=`echo "$0" | sed -e 's,.*/,,'` - -usage="\ -Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS - -Canonicalize a configuration name. - -Operation modes: - -h, --help print this help, then exit - -t, --time-stamp print date of last modification, then exit - -v, --version print version number, then exit - -Report bugs and patches to <config-patches@gnu.org>." - -version="\ -GNU config.sub ($timestamp) - -Copyright 1992-2016 Free Software Foundation, Inc. - -This is free software; see the source for copying conditions. There is NO -warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." - -help=" -Try \`$me --help' for more information." - -# Parse command line -while test $# -gt 0 ; do - case $1 in - --time-stamp | --time* | -t ) - echo "$timestamp" ; exit ;; - --version | -v ) - echo "$version" ; exit ;; - --help | --h* | -h ) - echo "$usage"; exit ;; - -- ) # Stop option processing - shift; break ;; - - ) # Use stdin as input. - break ;; - -* ) - echo "$me: invalid option $1$help" - exit 1 ;; - - *local*) - # First pass through any local machine types. - echo $1 - exit ;; - - * ) - break ;; - esac -done - -case $# in - 0) echo "$me: missing argument$help" >&2 - exit 1;; - 1) ;; - *) echo "$me: too many arguments$help" >&2 - exit 1;; -esac - -# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). -# Here we must recognize all the valid KERNEL-OS combinations. -maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` -case $maybe_os in - nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ - linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ - knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \ - kopensolaris*-gnu* | cloudabi*-eabi* | \ - storm-chaos* | os2-emx* | rtmk-nova*) - os=-$maybe_os - basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` - ;; - android-linux) - os=-linux-android - basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown - ;; - *) - basic_machine=`echo $1 | sed 's/-[^-]*$//'` - if [ $basic_machine != $1 ] - then os=`echo $1 | sed 's/.*-/-/'` - else os=; fi - ;; -esac - -### Let's recognize common machines as not being operating systems so -### that things like config.sub decstation-3100 work. We also -### recognize some manufacturers as not being operating systems, so we -### can provide default operating systems below. -case $os in - -sun*os*) - # Prevent following clause from handling this invalid input. - ;; - -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ - -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ - -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ - -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ - -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ - -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ - -apple | -axis | -knuth | -cray | -microblaze*) - os= - basic_machine=$1 - ;; - -bluegene*) - os=-cnk - ;; - -sim | -cisco | -oki | -wec | -winbond) - os= - basic_machine=$1 - ;; - -scout) - ;; - -wrs) - os=-vxworks - basic_machine=$1 - ;; - -chorusos*) - os=-chorusos - basic_machine=$1 - ;; - -chorusrdb) - os=-chorusrdb - basic_machine=$1 - ;; - -hiux*) - os=-hiuxwe2 - ;; - -sco6) - os=-sco5v6 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco5) - os=-sco3.2v5 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco4) - os=-sco3.2v4 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco3.2.[4-9]*) - os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco3.2v[4-9]*) - # Don't forget version if it is 3.2v4 or newer. - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco5v6*) - # Don't forget version if it is 3.2v4 or newer. - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco*) - os=-sco3.2v2 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -udk*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -isc) - os=-isc2.2 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -clix*) - basic_machine=clipper-intergraph - ;; - -isc*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -lynx*178) - os=-lynxos178 - ;; - -lynx*5) - os=-lynxos5 - ;; - -lynx*) - os=-lynxos - ;; - -ptx*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` - ;; - -windowsnt*) - os=`echo $os | sed -e 's/windowsnt/winnt/'` - ;; - -psos*) - os=-psos - ;; - -mint | -mint[0-9]*) - basic_machine=m68k-atari - os=-mint - ;; -esac - -# Decode aliases for certain CPU-COMPANY combinations. -case $basic_machine in - # Recognize the basic CPU types without company name. - # Some are omitted here because they have special meanings below. - 1750a | 580 \ - | a29k \ - | aarch64 | aarch64_be \ - | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ - | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ - | am33_2.0 \ - | arc | arceb \ - | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \ - | avr | avr32 \ - | ba \ - | be32 | be64 \ - | bfin \ - | c4x | c8051 | clipper \ - | d10v | d30v | dlx | dsp16xx \ - | e2k | epiphany \ - | fido | fr30 | frv | ft32 \ - | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ - | hexagon \ - | i370 | i860 | i960 | ia64 \ - | ip2k | iq2000 \ - | k1om \ - | le32 | le64 \ - | lm32 \ - | m32c | m32r | m32rle | m68000 | m68k | m88k \ - | maxq | mb | microblaze | microblazeel | mcore | mep | metag \ - | mips | mipsbe | mipseb | mipsel | mipsle \ - | mips16 \ - | mips64 | mips64el \ - | mips64octeon | mips64octeonel \ - | mips64orion | mips64orionel \ - | mips64r5900 | mips64r5900el \ - | mips64vr | mips64vrel \ - | mips64vr4100 | mips64vr4100el \ - | mips64vr4300 | mips64vr4300el \ - | mips64vr5000 | mips64vr5000el \ - | mips64vr5900 | mips64vr5900el \ - | mipsisa32 | mipsisa32el \ - | mipsisa32r2 | mipsisa32r2el \ - | mipsisa32r6 | mipsisa32r6el \ - | mipsisa64 | mipsisa64el \ - | mipsisa64r2 | mipsisa64r2el \ - | mipsisa64r6 | mipsisa64r6el \ - | mipsisa64sb1 | mipsisa64sb1el \ - | mipsisa64sr71k | mipsisa64sr71kel \ - | mipsr5900 | mipsr5900el \ - | mipstx39 | mipstx39el \ - | mn10200 | mn10300 \ - | moxie \ - | mt \ - | msp430 \ - | nds32 | nds32le | nds32be \ - | nios | nios2 | nios2eb | nios2el \ - | ns16k | ns32k \ - | open8 | or1k | or1knd | or32 \ - | pdp10 | pdp11 | pj | pjl \ - | powerpc | powerpc64 | powerpc64le | powerpcle \ - | pru \ - | pyramid \ - | riscv32 | riscv64 \ - | rl78 | rx \ - | score \ - | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[234]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ - | sh64 | sh64le \ - | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ - | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ - | spu \ - | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ - | ubicom32 \ - | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ - | visium \ - | we32k \ - | x86 | xc16x | xstormy16 | xtensa \ - | z8k | z80) - basic_machine=$basic_machine-unknown - ;; - c54x) - basic_machine=tic54x-unknown - ;; - c55x) - basic_machine=tic55x-unknown - ;; - c6x) - basic_machine=tic6x-unknown - ;; - leon|leon[3-9]) - basic_machine=sparc-$basic_machine - ;; - m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip) - basic_machine=$basic_machine-unknown - os=-none - ;; - m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) - ;; - ms1) - basic_machine=mt-unknown - ;; - - strongarm | thumb | xscale) - basic_machine=arm-unknown - ;; - xgate) - basic_machine=$basic_machine-unknown - os=-none - ;; - xscaleeb) - basic_machine=armeb-unknown - ;; - - xscaleel) - basic_machine=armel-unknown - ;; - - # We use `pc' rather than `unknown' - # because (1) that's what they normally are, and - # (2) the word "unknown" tends to confuse beginning users. - i*86 | x86_64) - basic_machine=$basic_machine-pc - ;; - # Object if more than one company name word. - *-*-*) - echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 - exit 1 - ;; - # Recognize the basic CPU types with company name. - 580-* \ - | a29k-* \ - | aarch64-* | aarch64_be-* \ - | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ - | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ - | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \ - | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ - | avr-* | avr32-* \ - | ba-* \ - | be32-* | be64-* \ - | bfin-* | bs2000-* \ - | c[123]* | c30-* | [cjt]90-* | c4x-* \ - | c8051-* | clipper-* | craynv-* | cydra-* \ - | d10v-* | d30v-* | dlx-* \ - | e2k-* | elxsi-* \ - | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ - | h8300-* | h8500-* \ - | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ - | hexagon-* \ - | i*86-* | i860-* | i960-* | ia64-* \ - | ip2k-* | iq2000-* \ - | k1om-* \ - | le32-* | le64-* \ - | lm32-* \ - | m32c-* | m32r-* | m32rle-* \ - | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ - | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ - | microblaze-* | microblazeel-* \ - | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ - | mips16-* \ - | mips64-* | mips64el-* \ - | mips64octeon-* | mips64octeonel-* \ - | mips64orion-* | mips64orionel-* \ - | mips64r5900-* | mips64r5900el-* \ - | mips64vr-* | mips64vrel-* \ - | mips64vr4100-* | mips64vr4100el-* \ - | mips64vr4300-* | mips64vr4300el-* \ - | mips64vr5000-* | mips64vr5000el-* \ - | mips64vr5900-* | mips64vr5900el-* \ - | mipsisa32-* | mipsisa32el-* \ - | mipsisa32r2-* | mipsisa32r2el-* \ - | mipsisa32r6-* | mipsisa32r6el-* \ - | mipsisa64-* | mipsisa64el-* \ - | mipsisa64r2-* | mipsisa64r2el-* \ - | mipsisa64r6-* | mipsisa64r6el-* \ - | mipsisa64sb1-* | mipsisa64sb1el-* \ - | mipsisa64sr71k-* | mipsisa64sr71kel-* \ - | mipsr5900-* | mipsr5900el-* \ - | mipstx39-* | mipstx39el-* \ - | mmix-* \ - | mt-* \ - | msp430-* \ - | nds32-* | nds32le-* | nds32be-* \ - | nios-* | nios2-* | nios2eb-* | nios2el-* \ - | none-* | np1-* | ns16k-* | ns32k-* \ - | open8-* \ - | or1k*-* \ - | orion-* \ - | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ - | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ - | pru-* \ - | pyramid-* \ - | riscv32-* | riscv64-* \ - | rl78-* | romp-* | rs6000-* | rx-* \ - | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ - | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ - | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ - | sparclite-* \ - | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx*-* \ - | tahoe-* \ - | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ - | tile*-* \ - | tron-* \ - | ubicom32-* \ - | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ - | vax-* \ - | visium-* \ - | we32k-* \ - | x86-* | x86_64-* | xc16x-* | xps100-* \ - | xstormy16-* | xtensa*-* \ - | ymp-* \ - | z8k-* | z80-*) - ;; - # Recognize the basic CPU types without company name, with glob match. - xtensa*) - basic_machine=$basic_machine-unknown - ;; - # Recognize the various machine names and aliases which stand - # for a CPU type and a company and sometimes even an OS. - 386bsd) - basic_machine=i386-unknown - os=-bsd - ;; - 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) - basic_machine=m68000-att - ;; - 3b*) - basic_machine=we32k-att - ;; - a29khif) - basic_machine=a29k-amd - os=-udi - ;; - abacus) - basic_machine=abacus-unknown - ;; - adobe68k) - basic_machine=m68010-adobe - os=-scout - ;; - alliant | fx80) - basic_machine=fx80-alliant - ;; - altos | altos3068) - basic_machine=m68k-altos - ;; - am29k) - basic_machine=a29k-none - os=-bsd - ;; - amd64) - basic_machine=x86_64-pc - ;; - amd64-*) - basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - amdahl) - basic_machine=580-amdahl - os=-sysv - ;; - amiga | amiga-*) - basic_machine=m68k-unknown - ;; - amigaos | amigados) - basic_machine=m68k-unknown - os=-amigaos - ;; - amigaunix | amix) - basic_machine=m68k-unknown - os=-sysv4 - ;; - apollo68) - basic_machine=m68k-apollo - os=-sysv - ;; - apollo68bsd) - basic_machine=m68k-apollo - os=-bsd - ;; - aros) - basic_machine=i386-pc - os=-aros - ;; - asmjs) - basic_machine=asmjs-unknown - ;; - aux) - basic_machine=m68k-apple - os=-aux - ;; - balance) - basic_machine=ns32k-sequent - os=-dynix - ;; - blackfin) - basic_machine=bfin-unknown - os=-linux - ;; - blackfin-*) - basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` - os=-linux - ;; - bluegene*) - basic_machine=powerpc-ibm - os=-cnk - ;; - c54x-*) - basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - c55x-*) - basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - c6x-*) - basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - c90) - basic_machine=c90-cray - os=-unicos - ;; - cegcc) - basic_machine=arm-unknown - os=-cegcc - ;; - convex-c1) - basic_machine=c1-convex - os=-bsd - ;; - convex-c2) - basic_machine=c2-convex - os=-bsd - ;; - convex-c32) - basic_machine=c32-convex - os=-bsd - ;; - convex-c34) - basic_machine=c34-convex - os=-bsd - ;; - convex-c38) - basic_machine=c38-convex - os=-bsd - ;; - cray | j90) - basic_machine=j90-cray - os=-unicos - ;; - craynv) - basic_machine=craynv-cray - os=-unicosmp - ;; - cr16 | cr16-*) - basic_machine=cr16-unknown - os=-elf - ;; - crds | unos) - basic_machine=m68k-crds - ;; - crisv32 | crisv32-* | etraxfs*) - basic_machine=crisv32-axis - ;; - cris | cris-* | etrax*) - basic_machine=cris-axis - ;; - crx) - basic_machine=crx-unknown - os=-elf - ;; - da30 | da30-*) - basic_machine=m68k-da30 - ;; - decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) - basic_machine=mips-dec - ;; - decsystem10* | dec10*) - basic_machine=pdp10-dec - os=-tops10 - ;; - decsystem20* | dec20*) - basic_machine=pdp10-dec - os=-tops20 - ;; - delta | 3300 | motorola-3300 | motorola-delta \ - | 3300-motorola | delta-motorola) - basic_machine=m68k-motorola - ;; - delta88) - basic_machine=m88k-motorola - os=-sysv3 - ;; - dicos) - basic_machine=i686-pc - os=-dicos - ;; - djgpp) - basic_machine=i586-pc - os=-msdosdjgpp - ;; - dpx20 | dpx20-*) - basic_machine=rs6000-bull - os=-bosx - ;; - dpx2* | dpx2*-bull) - basic_machine=m68k-bull - os=-sysv3 - ;; - e500v[12]) - basic_machine=powerpc-unknown - os=$os"spe" - ;; - e500v[12]-*) - basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` - os=$os"spe" - ;; - ebmon29k) - basic_machine=a29k-amd - os=-ebmon - ;; - elxsi) - basic_machine=elxsi-elxsi - os=-bsd - ;; - encore | umax | mmax) - basic_machine=ns32k-encore - ;; - es1800 | OSE68k | ose68k | ose | OSE) - basic_machine=m68k-ericsson - os=-ose - ;; - fx2800) - basic_machine=i860-alliant - ;; - genix) - basic_machine=ns32k-ns - ;; - gmicro) - basic_machine=tron-gmicro - os=-sysv - ;; - go32) - basic_machine=i386-pc - os=-go32 - ;; - h3050r* | hiux*) - basic_machine=hppa1.1-hitachi - os=-hiuxwe2 - ;; - h8300hms) - basic_machine=h8300-hitachi - os=-hms - ;; - h8300xray) - basic_machine=h8300-hitachi - os=-xray - ;; - h8500hms) - basic_machine=h8500-hitachi - os=-hms - ;; - harris) - basic_machine=m88k-harris - os=-sysv3 - ;; - hp300-*) - basic_machine=m68k-hp - ;; - hp300bsd) - basic_machine=m68k-hp - os=-bsd - ;; - hp300hpux) - basic_machine=m68k-hp - os=-hpux - ;; - hp3k9[0-9][0-9] | hp9[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hp9k2[0-9][0-9] | hp9k31[0-9]) - basic_machine=m68000-hp - ;; - hp9k3[2-9][0-9]) - basic_machine=m68k-hp - ;; - hp9k6[0-9][0-9] | hp6[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hp9k7[0-79][0-9] | hp7[0-79][0-9]) - basic_machine=hppa1.1-hp - ;; - hp9k78[0-9] | hp78[0-9]) - # FIXME: really hppa2.0-hp - basic_machine=hppa1.1-hp - ;; - hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) - # FIXME: really hppa2.0-hp - basic_machine=hppa1.1-hp - ;; - hp9k8[0-9][13679] | hp8[0-9][13679]) - basic_machine=hppa1.1-hp - ;; - hp9k8[0-9][0-9] | hp8[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hppa-next) - os=-nextstep3 - ;; - hppaosf) - basic_machine=hppa1.1-hp - os=-osf - ;; - hppro) - basic_machine=hppa1.1-hp - os=-proelf - ;; - i370-ibm* | ibm*) - basic_machine=i370-ibm - ;; - i*86v32) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv32 - ;; - i*86v4*) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv4 - ;; - i*86v) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv - ;; - i*86sol2) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-solaris2 - ;; - i386mach) - basic_machine=i386-mach - os=-mach - ;; - i386-vsta | vsta) - basic_machine=i386-unknown - os=-vsta - ;; - iris | iris4d) - basic_machine=mips-sgi - case $os in - -irix*) - ;; - *) - os=-irix4 - ;; - esac - ;; - isi68 | isi) - basic_machine=m68k-isi - os=-sysv - ;; - leon-*|leon[3-9]-*) - basic_machine=sparc-`echo $basic_machine | sed 's/-.*//'` - ;; - m68knommu) - basic_machine=m68k-unknown - os=-linux - ;; - m68knommu-*) - basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` - os=-linux - ;; - m88k-omron*) - basic_machine=m88k-omron - ;; - magnum | m3230) - basic_machine=mips-mips - os=-sysv - ;; - merlin) - basic_machine=ns32k-utek - os=-sysv - ;; - microblaze*) - basic_machine=microblaze-xilinx - ;; - mingw64) - basic_machine=x86_64-pc - os=-mingw64 - ;; - mingw32) - basic_machine=i686-pc - os=-mingw32 - ;; - mingw32ce) - basic_machine=arm-unknown - os=-mingw32ce - ;; - miniframe) - basic_machine=m68000-convergent - ;; - *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) - basic_machine=m68k-atari - os=-mint - ;; - mips3*-*) - basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` - ;; - mips3*) - basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown - ;; - monitor) - basic_machine=m68k-rom68k - os=-coff - ;; - morphos) - basic_machine=powerpc-unknown - os=-morphos - ;; - moxiebox) - basic_machine=moxie-unknown - os=-moxiebox - ;; - msdos) - basic_machine=i386-pc - os=-msdos - ;; - ms1-*) - basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` - ;; - msys) - basic_machine=i686-pc - os=-msys - ;; - mvs) - basic_machine=i370-ibm - os=-mvs - ;; - nacl) - basic_machine=le32-unknown - os=-nacl - ;; - ncr3000) - basic_machine=i486-ncr - os=-sysv4 - ;; - netbsd386) - basic_machine=i386-unknown - os=-netbsd - ;; - netwinder) - basic_machine=armv4l-rebel - os=-linux - ;; - news | news700 | news800 | news900) - basic_machine=m68k-sony - os=-newsos - ;; - news1000) - basic_machine=m68030-sony - os=-newsos - ;; - news-3600 | risc-news) - basic_machine=mips-sony - os=-newsos - ;; - necv70) - basic_machine=v70-nec - os=-sysv - ;; - next | m*-next ) - basic_machine=m68k-next - case $os in - -nextstep* ) - ;; - -ns2*) - os=-nextstep2 - ;; - *) - os=-nextstep3 - ;; - esac - ;; - nh3000) - basic_machine=m68k-harris - os=-cxux - ;; - nh[45]000) - basic_machine=m88k-harris - os=-cxux - ;; - nindy960) - basic_machine=i960-intel - os=-nindy - ;; - mon960) - basic_machine=i960-intel - os=-mon960 - ;; - nonstopux) - basic_machine=mips-compaq - os=-nonstopux - ;; - np1) - basic_machine=np1-gould - ;; - neo-tandem) - basic_machine=neo-tandem - ;; - nse-tandem) - basic_machine=nse-tandem - ;; - nsr-tandem) - basic_machine=nsr-tandem - ;; - op50n-* | op60c-*) - basic_machine=hppa1.1-oki - os=-proelf - ;; - openrisc | openrisc-*) - basic_machine=or32-unknown - ;; - os400) - basic_machine=powerpc-ibm - os=-os400 - ;; - OSE68000 | ose68000) - basic_machine=m68000-ericsson - os=-ose - ;; - os68k) - basic_machine=m68k-none - os=-os68k - ;; - pa-hitachi) - basic_machine=hppa1.1-hitachi - os=-hiuxwe2 - ;; - paragon) - basic_machine=i860-intel - os=-osf - ;; - parisc) - basic_machine=hppa-unknown - os=-linux - ;; - parisc-*) - basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` - os=-linux - ;; - pbd) - basic_machine=sparc-tti - ;; - pbb) - basic_machine=m68k-tti - ;; - pc532 | pc532-*) - basic_machine=ns32k-pc532 - ;; - pc98) - basic_machine=i386-pc - ;; - pc98-*) - basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentium | p5 | k5 | k6 | nexgen | viac3) - basic_machine=i586-pc - ;; - pentiumpro | p6 | 6x86 | athlon | athlon_*) - basic_machine=i686-pc - ;; - pentiumii | pentium2 | pentiumiii | pentium3) - basic_machine=i686-pc - ;; - pentium4) - basic_machine=i786-pc - ;; - pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) - basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentiumpro-* | p6-* | 6x86-* | athlon-*) - basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) - basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentium4-*) - basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pn) - basic_machine=pn-gould - ;; - power) basic_machine=power-ibm - ;; - ppc | ppcbe) basic_machine=powerpc-unknown - ;; - ppc-* | ppcbe-*) - basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ppcle | powerpclittle) - basic_machine=powerpcle-unknown - ;; - ppcle-* | powerpclittle-*) - basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ppc64) basic_machine=powerpc64-unknown - ;; - ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ppc64le | powerpc64little) - basic_machine=powerpc64le-unknown - ;; - ppc64le-* | powerpc64little-*) - basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ps2) - basic_machine=i386-ibm - ;; - pw32) - basic_machine=i586-unknown - os=-pw32 - ;; - rdos | rdos64) - basic_machine=x86_64-pc - os=-rdos - ;; - rdos32) - basic_machine=i386-pc - os=-rdos - ;; - rom68k) - basic_machine=m68k-rom68k - os=-coff - ;; - rm[46]00) - basic_machine=mips-siemens - ;; - rtpc | rtpc-*) - basic_machine=romp-ibm - ;; - s390 | s390-*) - basic_machine=s390-ibm - ;; - s390x | s390x-*) - basic_machine=s390x-ibm - ;; - sa29200) - basic_machine=a29k-amd - os=-udi - ;; - sb1) - basic_machine=mipsisa64sb1-unknown - ;; - sb1el) - basic_machine=mipsisa64sb1el-unknown - ;; - sde) - basic_machine=mipsisa32-sde - os=-elf - ;; - sei) - basic_machine=mips-sei - os=-seiux - ;; - sequent) - basic_machine=i386-sequent - ;; - sh) - basic_machine=sh-hitachi - os=-hms - ;; - sh5el) - basic_machine=sh5le-unknown - ;; - sh64) - basic_machine=sh64-unknown - ;; - sparclite-wrs | simso-wrs) - basic_machine=sparclite-wrs - os=-vxworks - ;; - sps7) - basic_machine=m68k-bull - os=-sysv2 - ;; - spur) - basic_machine=spur-unknown - ;; - st2000) - basic_machine=m68k-tandem - ;; - stratus) - basic_machine=i860-stratus - os=-sysv4 - ;; - strongarm-* | thumb-*) - basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - sun2) - basic_machine=m68000-sun - ;; - sun2os3) - basic_machine=m68000-sun - os=-sunos3 - ;; - sun2os4) - basic_machine=m68000-sun - os=-sunos4 - ;; - sun3os3) - basic_machine=m68k-sun - os=-sunos3 - ;; - sun3os4) - basic_machine=m68k-sun - os=-sunos4 - ;; - sun4os3) - basic_machine=sparc-sun - os=-sunos3 - ;; - sun4os4) - basic_machine=sparc-sun - os=-sunos4 - ;; - sun4sol2) - basic_machine=sparc-sun - os=-solaris2 - ;; - sun3 | sun3-*) - basic_machine=m68k-sun - ;; - sun4) - basic_machine=sparc-sun - ;; - sun386 | sun386i | roadrunner) - basic_machine=i386-sun - ;; - sv1) - basic_machine=sv1-cray - os=-unicos - ;; - symmetry) - basic_machine=i386-sequent - os=-dynix - ;; - t3e) - basic_machine=alphaev5-cray - os=-unicos - ;; - t90) - basic_machine=t90-cray - os=-unicos - ;; - tile*) - basic_machine=$basic_machine-unknown - os=-linux-gnu - ;; - tx39) - basic_machine=mipstx39-unknown - ;; - tx39el) - basic_machine=mipstx39el-unknown - ;; - toad1) - basic_machine=pdp10-xkl - os=-tops20 - ;; - tower | tower-32) - basic_machine=m68k-ncr - ;; - tpf) - basic_machine=s390x-ibm - os=-tpf - ;; - udi29k) - basic_machine=a29k-amd - os=-udi - ;; - ultra3) - basic_machine=a29k-nyu - os=-sym1 - ;; - v810 | necv810) - basic_machine=v810-nec - os=-none - ;; - vaxv) - basic_machine=vax-dec - os=-sysv - ;; - vms) - basic_machine=vax-dec - os=-vms - ;; - vpp*|vx|vx-*) - basic_machine=f301-fujitsu - ;; - vxworks960) - basic_machine=i960-wrs - os=-vxworks - ;; - vxworks68) - basic_machine=m68k-wrs - os=-vxworks - ;; - vxworks29k) - basic_machine=a29k-wrs - os=-vxworks - ;; - w65*) - basic_machine=w65-wdc - os=-none - ;; - w89k-*) - basic_machine=hppa1.1-winbond - os=-proelf - ;; - xbox) - basic_machine=i686-pc - os=-mingw32 - ;; - xps | xps100) - basic_machine=xps100-honeywell - ;; - xscale-* | xscalee[bl]-*) - basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` - ;; - ymp) - basic_machine=ymp-cray - os=-unicos - ;; - z8k-*-coff) - basic_machine=z8k-unknown - os=-sim - ;; - z80-*-coff) - basic_machine=z80-unknown - os=-sim - ;; - none) - basic_machine=none-none - os=-none - ;; - -# Here we handle the default manufacturer of certain CPU types. It is in -# some cases the only manufacturer, in others, it is the most popular. - w89k) - basic_machine=hppa1.1-winbond - ;; - op50n) - basic_machine=hppa1.1-oki - ;; - op60c) - basic_machine=hppa1.1-oki - ;; - romp) - basic_machine=romp-ibm - ;; - mmix) - basic_machine=mmix-knuth - ;; - rs6000) - basic_machine=rs6000-ibm - ;; - vax) - basic_machine=vax-dec - ;; - pdp10) - # there are many clones, so DEC is not a safe bet - basic_machine=pdp10-unknown - ;; - pdp11) - basic_machine=pdp11-dec - ;; - we32k) - basic_machine=we32k-att - ;; - sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) - basic_machine=sh-unknown - ;; - sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) - basic_machine=sparc-sun - ;; - cydra) - basic_machine=cydra-cydrome - ;; - orion) - basic_machine=orion-highlevel - ;; - orion105) - basic_machine=clipper-highlevel - ;; - mac | mpw | mac-mpw) - basic_machine=m68k-apple - ;; - pmac | pmac-mpw) - basic_machine=powerpc-apple - ;; - *-unknown) - # Make sure to match an already-canonicalized machine name. - ;; - *) - echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 - exit 1 - ;; -esac - -# Here we canonicalize certain aliases for manufacturers. -case $basic_machine in - *-digital*) - basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` - ;; - *-commodore*) - basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` - ;; - *) - ;; -esac - -# Decode manufacturer-specific aliases for certain operating systems. - -if [ x"$os" != x"" ] -then -case $os in - # First match some system type aliases - # that might get confused with valid system types. - # -solaris* is a basic system type, with this one exception. - -auroraux) - os=-auroraux - ;; - -solaris1 | -solaris1.*) - os=`echo $os | sed -e 's|solaris1|sunos4|'` - ;; - -solaris) - os=-solaris2 - ;; - -svr4*) - os=-sysv4 - ;; - -unixware*) - os=-sysv4.2uw - ;; - -gnu/linux*) - os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` - ;; - # First accept the basic system types. - # The portable systems comes first. - # Each alternative MUST END IN A *, to match a version number. - # -sysv* is not here because it comes later, after sysvr4. - -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ - | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ - | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ - | -sym* | -kopensolaris* | -plan9* \ - | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ - | -aos* | -aros* | -cloudabi* | -sortix* \ - | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ - | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ - | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ - | -bitrig* | -openbsd* | -solidbsd* | -libertybsd* \ - | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ - | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ - | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ - | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ - | -chorusos* | -chorusrdb* | -cegcc* \ - | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ - | -midipix* | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ - | -linux-newlib* | -linux-musl* | -linux-uclibc* \ - | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \ - | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ - | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ - | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ - | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ - | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ - | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ - | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* \ - | -onefs* | -tirtos* | -phoenix* | -fuchsia*) - # Remember, each alternative MUST END IN *, to match a version number. - ;; - -qnx*) - case $basic_machine in - x86-* | i*86-*) - ;; - *) - os=-nto$os - ;; - esac - ;; - -nto-qnx*) - ;; - -nto*) - os=`echo $os | sed -e 's|nto|nto-qnx|'` - ;; - -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ - | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ - | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) - ;; - -mac*) - os=`echo $os | sed -e 's|mac|macos|'` - ;; - -linux-dietlibc) - os=-linux-dietlibc - ;; - -linux*) - os=`echo $os | sed -e 's|linux|linux-gnu|'` - ;; - -sunos5*) - os=`echo $os | sed -e 's|sunos5|solaris2|'` - ;; - -sunos6*) - os=`echo $os | sed -e 's|sunos6|solaris3|'` - ;; - -opened*) - os=-openedition - ;; - -os400*) - os=-os400 - ;; - -wince*) - os=-wince - ;; - -osfrose*) - os=-osfrose - ;; - -osf*) - os=-osf - ;; - -utek*) - os=-bsd - ;; - -dynix*) - os=-bsd - ;; - -acis*) - os=-aos - ;; - -atheos*) - os=-atheos - ;; - -syllable*) - os=-syllable - ;; - -386bsd) - os=-bsd - ;; - -ctix* | -uts*) - os=-sysv - ;; - -nova*) - os=-rtmk-nova - ;; - -ns2 ) - os=-nextstep2 - ;; - -nsk*) - os=-nsk - ;; - # Preserve the version number of sinix5. - -sinix5.*) - os=`echo $os | sed -e 's|sinix|sysv|'` - ;; - -sinix*) - os=-sysv4 - ;; - -tpf*) - os=-tpf - ;; - -triton*) - os=-sysv3 - ;; - -oss*) - os=-sysv3 - ;; - -svr4) - os=-sysv4 - ;; - -svr3) - os=-sysv3 - ;; - -sysvr4) - os=-sysv4 - ;; - # This must come after -sysvr4. - -sysv*) - ;; - -ose*) - os=-ose - ;; - -es1800*) - os=-ose - ;; - -xenix) - os=-xenix - ;; - -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) - os=-mint - ;; - -aros*) - os=-aros - ;; - -zvmoe) - os=-zvmoe - ;; - -dicos*) - os=-dicos - ;; - -nacl*) - ;; - -ios) - ;; - -none) - ;; - *) - # Get rid of the `-' at the beginning of $os. - os=`echo $os | sed 's/[^-]*-//'` - echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 - exit 1 - ;; -esac -else - -# Here we handle the default operating systems that come with various machines. -# The value should be what the vendor currently ships out the door with their -# machine or put another way, the most popular os provided with the machine. - -# Note that if you're going to try to match "-MANUFACTURER" here (say, -# "-sun"), then you have to tell the case statement up towards the top -# that MANUFACTURER isn't an operating system. Otherwise, code above -# will signal an error saying that MANUFACTURER isn't an operating -# system, and we'll never get to this point. - -case $basic_machine in - score-*) - os=-elf - ;; - spu-*) - os=-elf - ;; - *-acorn) - os=-riscix1.2 - ;; - arm*-rebel) - os=-linux - ;; - arm*-semi) - os=-aout - ;; - c4x-* | tic4x-*) - os=-coff - ;; - c8051-*) - os=-elf - ;; - hexagon-*) - os=-elf - ;; - tic54x-*) - os=-coff - ;; - tic55x-*) - os=-coff - ;; - tic6x-*) - os=-coff - ;; - # This must come before the *-dec entry. - pdp10-*) - os=-tops20 - ;; - pdp11-*) - os=-none - ;; - *-dec | vax-*) - os=-ultrix4.2 - ;; - m68*-apollo) - os=-domain - ;; - i386-sun) - os=-sunos4.0.2 - ;; - m68000-sun) - os=-sunos3 - ;; - m68*-cisco) - os=-aout - ;; - mep-*) - os=-elf - ;; - mips*-cisco) - os=-elf - ;; - mips*-*) - os=-elf - ;; - or32-*) - os=-coff - ;; - *-tti) # must be before sparc entry or we get the wrong os. - os=-sysv3 - ;; - sparc-* | *-sun) - os=-sunos4.1.1 - ;; - *-be) - os=-beos - ;; - *-haiku) - os=-haiku - ;; - *-ibm) - os=-aix - ;; - *-knuth) - os=-mmixware - ;; - *-wec) - os=-proelf - ;; - *-winbond) - os=-proelf - ;; - *-oki) - os=-proelf - ;; - *-hp) - os=-hpux - ;; - *-hitachi) - os=-hiux - ;; - i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) - os=-sysv - ;; - *-cbm) - os=-amigaos - ;; - *-dg) - os=-dgux - ;; - *-dolphin) - os=-sysv3 - ;; - m68k-ccur) - os=-rtu - ;; - m88k-omron*) - os=-luna - ;; - *-next ) - os=-nextstep - ;; - *-sequent) - os=-ptx - ;; - *-crds) - os=-unos - ;; - *-ns) - os=-genix - ;; - i370-*) - os=-mvs - ;; - *-next) - os=-nextstep3 - ;; - *-gould) - os=-sysv - ;; - *-highlevel) - os=-bsd - ;; - *-encore) - os=-bsd - ;; - *-sgi) - os=-irix - ;; - *-siemens) - os=-sysv4 - ;; - *-masscomp) - os=-rtu - ;; - f30[01]-fujitsu | f700-fujitsu) - os=-uxpv - ;; - *-rom68k) - os=-coff - ;; - *-*bug) - os=-coff - ;; - *-apple) - os=-macos - ;; - *-atari*) - os=-mint - ;; - *) - os=-none - ;; -esac -fi - -# Here we handle the case where we know the os, and the CPU type, but not the -# manufacturer. We pick the logical manufacturer. -vendor=unknown -case $basic_machine in - *-unknown) - case $os in - -riscix*) - vendor=acorn - ;; - -sunos*) - vendor=sun - ;; - -cnk*|-aix*) - vendor=ibm - ;; - -beos*) - vendor=be - ;; - -hpux*) - vendor=hp - ;; - -mpeix*) - vendor=hp - ;; - -hiux*) - vendor=hitachi - ;; - -unos*) - vendor=crds - ;; - -dgux*) - vendor=dg - ;; - -luna*) - vendor=omron - ;; - -genix*) - vendor=ns - ;; - -mvs* | -opened*) - vendor=ibm - ;; - -os400*) - vendor=ibm - ;; - -ptx*) - vendor=sequent - ;; - -tpf*) - vendor=ibm - ;; - -vxsim* | -vxworks* | -windiss*) - vendor=wrs - ;; - -aux*) - vendor=apple - ;; - -hms*) - vendor=hitachi - ;; - -mpw* | -macos*) - vendor=apple - ;; - -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) - vendor=atari - ;; - -vos*) - vendor=stratus - ;; - esac - basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` - ;; -esac - -echo $basic_machine$os -exit - -# Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "timestamp='" -# time-stamp-format: "%:y-%02m-%02d" -# time-stamp-end: "'" -# End: ->>>>>>> main diff --git a/contrib/jemalloc/configure.ac b/contrib/jemalloc/configure.ac index f7285a6154b9..f6d25f3345ee 100644 --- a/contrib/jemalloc/configure.ac +++ b/contrib/jemalloc/configure.ac @@ -1,4 +1,3 @@ -<<<<<<< HEAD dnl Process this file with autoconf to produce a configure script. AC_PREREQ(2.68) AC_INIT([Makefile.in]) @@ -2668,2412 +2667,3 @@ AC_MSG_RESULT([lazy_lock : ${enable_lazy_lock}]) AC_MSG_RESULT([cache-oblivious : ${enable_cache_oblivious}]) AC_MSG_RESULT([cxx : ${enable_cxx}]) AC_MSG_RESULT([===============================================================================]) -||||||| dec341af7695 -======= -dnl Process this file with autoconf to produce a configure script. -AC_PREREQ(2.68) -AC_INIT([Makefile.in]) - -AC_CONFIG_AUX_DIR([build-aux]) - -dnl ============================================================================ -dnl Custom macro definitions. - -dnl JE_CONCAT_VVV(r, a, b) -dnl -dnl Set $r to the concatenation of $a and $b, with a space separating them iff -dnl both $a and $b are non-empty. -AC_DEFUN([JE_CONCAT_VVV], -if test "x[$]{$2}" = "x" -o "x[$]{$3}" = "x" ; then - $1="[$]{$2}[$]{$3}" -else - $1="[$]{$2} [$]{$3}" -fi -) - -dnl JE_APPEND_VS(a, b) -dnl -dnl Set $a to the concatenation of $a and b, with a space separating them iff -dnl both $a and b are non-empty. -AC_DEFUN([JE_APPEND_VS], - T_APPEND_V=$2 - JE_CONCAT_VVV($1, $1, T_APPEND_V) -) - -CONFIGURE_CFLAGS= -SPECIFIED_CFLAGS="${CFLAGS}" -dnl JE_CFLAGS_ADD(cflag) -dnl -dnl CFLAGS is the concatenation of CONFIGURE_CFLAGS and SPECIFIED_CFLAGS -dnl (ignoring EXTRA_CFLAGS, which does not impact configure tests. This macro -dnl appends to CONFIGURE_CFLAGS and regenerates CFLAGS. -AC_DEFUN([JE_CFLAGS_ADD], -[ -AC_MSG_CHECKING([whether compiler supports $1]) -T_CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS}" -JE_APPEND_VS(CONFIGURE_CFLAGS, $1) -JE_CONCAT_VVV(CFLAGS, CONFIGURE_CFLAGS, SPECIFIED_CFLAGS) -AC_COMPILE_IFELSE([AC_LANG_PROGRAM( -[[ -]], [[ - return 0; -]])], - [je_cv_cflags_added=$1] - AC_MSG_RESULT([yes]), - [je_cv_cflags_added=] - AC_MSG_RESULT([no]) - [CONFIGURE_CFLAGS="${T_CONFIGURE_CFLAGS}"] -) -JE_CONCAT_VVV(CFLAGS, CONFIGURE_CFLAGS, SPECIFIED_CFLAGS) -]) - -dnl JE_CFLAGS_SAVE() -dnl JE_CFLAGS_RESTORE() -dnl -dnl Save/restore CFLAGS. Nesting is not supported. -AC_DEFUN([JE_CFLAGS_SAVE], -SAVED_CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS}" -) -AC_DEFUN([JE_CFLAGS_RESTORE], -CONFIGURE_CFLAGS="${SAVED_CONFIGURE_CFLAGS}" -JE_CONCAT_VVV(CFLAGS, CONFIGURE_CFLAGS, SPECIFIED_CFLAGS) -) - -CONFIGURE_CXXFLAGS= -SPECIFIED_CXXFLAGS="${CXXFLAGS}" -dnl JE_CXXFLAGS_ADD(cxxflag) -AC_DEFUN([JE_CXXFLAGS_ADD], -[ -AC_MSG_CHECKING([whether compiler supports $1]) -T_CONFIGURE_CXXFLAGS="${CONFIGURE_CXXFLAGS}" -JE_APPEND_VS(CONFIGURE_CXXFLAGS, $1) -JE_CONCAT_VVV(CXXFLAGS, CONFIGURE_CXXFLAGS, SPECIFIED_CXXFLAGS) -AC_LANG_PUSH([C++]) -AC_COMPILE_IFELSE([AC_LANG_PROGRAM( -[[ -]], [[ - return 0; -]])], - [je_cv_cxxflags_added=$1] - AC_MSG_RESULT([yes]), - [je_cv_cxxflags_added=] - AC_MSG_RESULT([no]) - [CONFIGURE_CXXFLAGS="${T_CONFIGURE_CXXFLAGS}"] -) -AC_LANG_POP([C++]) -JE_CONCAT_VVV(CXXFLAGS, CONFIGURE_CXXFLAGS, SPECIFIED_CXXFLAGS) -]) - -dnl JE_COMPILABLE(label, hcode, mcode, rvar) -dnl -dnl Use AC_LINK_IFELSE() rather than AC_COMPILE_IFELSE() so that linker errors -dnl cause failure. -AC_DEFUN([JE_COMPILABLE], -[ -AC_CACHE_CHECK([whether $1 is compilable], - [$4], - [AC_LINK_IFELSE([AC_LANG_PROGRAM([$2], - [$3])], - [$4=yes], - [$4=no])]) -]) - -dnl ============================================================================ - -CONFIG=`echo ${ac_configure_args} | sed -e 's#'"'"'\([^ ]*\)'"'"'#\1#g'` -AC_SUBST([CONFIG]) - -dnl Library revision. -rev=2 -AC_SUBST([rev]) - -srcroot=$srcdir -if test "x${srcroot}" = "x." ; then - srcroot="" -else - srcroot="${srcroot}/" -fi -AC_SUBST([srcroot]) -abs_srcroot="`cd \"${srcdir}\"; pwd`/" -AC_SUBST([abs_srcroot]) - -objroot="" -AC_SUBST([objroot]) -abs_objroot="`pwd`/" -AC_SUBST([abs_objroot]) - -dnl Munge install path variables. -if test "x$prefix" = "xNONE" ; then - prefix="/usr/local" -fi -if test "x$exec_prefix" = "xNONE" ; then - exec_prefix=$prefix -fi -PREFIX=$prefix -AC_SUBST([PREFIX]) -BINDIR=`eval echo $bindir` -BINDIR=`eval echo $BINDIR` -AC_SUBST([BINDIR]) -INCLUDEDIR=`eval echo $includedir` -INCLUDEDIR=`eval echo $INCLUDEDIR` -AC_SUBST([INCLUDEDIR]) -LIBDIR=`eval echo $libdir` -LIBDIR=`eval echo $LIBDIR` -AC_SUBST([LIBDIR]) -DATADIR=`eval echo $datadir` -DATADIR=`eval echo $DATADIR` -AC_SUBST([DATADIR]) -MANDIR=`eval echo $mandir` -MANDIR=`eval echo $MANDIR` -AC_SUBST([MANDIR]) - -dnl Support for building documentation. -AC_PATH_PROG([XSLTPROC], [xsltproc], [false], [$PATH]) -if test -d "/usr/share/xml/docbook/stylesheet/docbook-xsl" ; then - DEFAULT_XSLROOT="/usr/share/xml/docbook/stylesheet/docbook-xsl" -elif test -d "/usr/share/sgml/docbook/xsl-stylesheets" ; then - DEFAULT_XSLROOT="/usr/share/sgml/docbook/xsl-stylesheets" -else - dnl Documentation building will fail if this default gets used. - DEFAULT_XSLROOT="" -fi -AC_ARG_WITH([xslroot], - [AS_HELP_STRING([--with-xslroot=<path>], [XSL stylesheet root path])], [ -if test "x$with_xslroot" = "xno" ; then - XSLROOT="${DEFAULT_XSLROOT}" -else - XSLROOT="${with_xslroot}" -fi -], - XSLROOT="${DEFAULT_XSLROOT}" -) -if test "x$XSLTPROC" = "xfalse" ; then - XSLROOT="" -fi -AC_SUBST([XSLROOT]) - -dnl If CFLAGS isn't defined, set CFLAGS to something reasonable. Otherwise, -dnl just prevent autoconf from molesting CFLAGS. -CFLAGS=$CFLAGS -AC_PROG_CC - -if test "x$GCC" != "xyes" ; then - AC_CACHE_CHECK([whether compiler is MSVC], - [je_cv_msvc], - [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], - [ -#ifndef _MSC_VER - int fail[-1]; -#endif -])], - [je_cv_msvc=yes], - [je_cv_msvc=no])]) -fi - -dnl check if a cray prgenv wrapper compiler is being used -je_cv_cray_prgenv_wrapper="" -if test "x${PE_ENV}" != "x" ; then - case "${CC}" in - CC|cc) - je_cv_cray_prgenv_wrapper="yes" - ;; - *) - ;; - esac -fi - -AC_CACHE_CHECK([whether compiler is cray], - [je_cv_cray], - [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], - [ -#ifndef _CRAYC - int fail[-1]; -#endif -])], - [je_cv_cray=yes], - [je_cv_cray=no])]) - -if test "x${je_cv_cray}" = "xyes" ; then - AC_CACHE_CHECK([whether cray compiler version is 8.4], - [je_cv_cray_84], - [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], - [ -#if !(_RELEASE_MAJOR == 8 && _RELEASE_MINOR == 4) - int fail[-1]; -#endif -])], - [je_cv_cray_84=yes], - [je_cv_cray_84=no])]) -fi - -if test "x$GCC" = "xyes" ; then - JE_CFLAGS_ADD([-std=gnu11]) - if test "x$je_cv_cflags_added" = "x-std=gnu11" ; then - AC_DEFINE_UNQUOTED([JEMALLOC_HAS_RESTRICT]) - else - JE_CFLAGS_ADD([-std=gnu99]) - if test "x$je_cv_cflags_added" = "x-std=gnu99" ; then - AC_DEFINE_UNQUOTED([JEMALLOC_HAS_RESTRICT]) - fi - fi - JE_CFLAGS_ADD([-Wall]) - JE_CFLAGS_ADD([-Wextra]) - JE_CFLAGS_ADD([-Wshorten-64-to-32]) - JE_CFLAGS_ADD([-Wsign-compare]) - JE_CFLAGS_ADD([-Wundef]) - JE_CFLAGS_ADD([-Wno-format-zero-length]) - JE_CFLAGS_ADD([-pipe]) - JE_CFLAGS_ADD([-g3]) -elif test "x$je_cv_msvc" = "xyes" ; then - CC="$CC -nologo" - JE_CFLAGS_ADD([-Zi]) - JE_CFLAGS_ADD([-MT]) - JE_CFLAGS_ADD([-W3]) - JE_CFLAGS_ADD([-FS]) - JE_APPEND_VS(CPPFLAGS, -I${srcdir}/include/msvc_compat) -fi -if test "x$je_cv_cray" = "xyes" ; then - dnl cray compiler 8.4 has an inlining bug - if test "x$je_cv_cray_84" = "xyes" ; then - JE_CFLAGS_ADD([-hipa2]) - JE_CFLAGS_ADD([-hnognu]) - fi - dnl ignore unreachable code warning - JE_CFLAGS_ADD([-hnomessage=128]) - dnl ignore redefinition of "malloc", "free", etc warning - JE_CFLAGS_ADD([-hnomessage=1357]) -fi -AC_SUBST([CONFIGURE_CFLAGS]) -AC_SUBST([SPECIFIED_CFLAGS]) -AC_SUBST([EXTRA_CFLAGS]) -AC_PROG_CPP - -AC_ARG_ENABLE([cxx], - [AS_HELP_STRING([--disable-cxx], [Disable C++ integration])], -if test "x$enable_cxx" = "xno" ; then - enable_cxx="0" -else - enable_cxx="1" -fi -, -enable_cxx="1" -) -if test "x$enable_cxx" = "x1" ; then - dnl Require at least c++14, which is the first version to support sized - dnl deallocation. C++ support is not compiled otherwise. - m4_include([m4/ax_cxx_compile_stdcxx.m4]) - AX_CXX_COMPILE_STDCXX([14], [noext], [optional]) - if test "x${HAVE_CXX14}" = "x1" ; then - JE_CXXFLAGS_ADD([-Wall]) - JE_CXXFLAGS_ADD([-Wextra]) - JE_CXXFLAGS_ADD([-g3]) - - SAVED_LIBS="${LIBS}" - JE_APPEND_VS(LIBS, -lstdc++) - JE_COMPILABLE([libstdc++ linkage], [ -#include <stdlib.h> -], [[ - int *arr = (int *)malloc(sizeof(int) * 42); - if (arr == NULL) - return 1; -]], [je_cv_libstdcxx]) - if test "x${je_cv_libstdcxx}" = "xno" ; then - LIBS="${SAVED_LIBS}" - fi - else - enable_cxx="0" - fi -fi -AC_SUBST([enable_cxx]) -AC_SUBST([CONFIGURE_CXXFLAGS]) -AC_SUBST([SPECIFIED_CXXFLAGS]) -AC_SUBST([EXTRA_CXXFLAGS]) - -AC_C_BIGENDIAN([ac_cv_big_endian=1], [ac_cv_big_endian=0]) -if test "x${ac_cv_big_endian}" = "x1" ; then - AC_DEFINE_UNQUOTED([JEMALLOC_BIG_ENDIAN], [ ]) -fi - -if test "x${je_cv_msvc}" = "xyes" -a "x${ac_cv_header_inttypes_h}" = "xno"; then - JE_APPEND_VS(CPPFLAGS, -I${srcdir}/include/msvc_compat/C99) -fi - -if test "x${je_cv_msvc}" = "xyes" ; then - LG_SIZEOF_PTR=LG_SIZEOF_PTR_WIN - AC_MSG_RESULT([Using a predefined value for sizeof(void *): 4 for 32-bit, 8 for 64-bit]) -else - AC_CHECK_SIZEOF([void *]) - if test "x${ac_cv_sizeof_void_p}" = "x8" ; then - LG_SIZEOF_PTR=3 - elif test "x${ac_cv_sizeof_void_p}" = "x4" ; then - LG_SIZEOF_PTR=2 - else - AC_MSG_ERROR([Unsupported pointer size: ${ac_cv_sizeof_void_p}]) - fi -fi -AC_DEFINE_UNQUOTED([LG_SIZEOF_PTR], [$LG_SIZEOF_PTR]) - -AC_CHECK_SIZEOF([int]) -if test "x${ac_cv_sizeof_int}" = "x8" ; then - LG_SIZEOF_INT=3 -elif test "x${ac_cv_sizeof_int}" = "x4" ; then - LG_SIZEOF_INT=2 -else - AC_MSG_ERROR([Unsupported int size: ${ac_cv_sizeof_int}]) -fi -AC_DEFINE_UNQUOTED([LG_SIZEOF_INT], [$LG_SIZEOF_INT]) - -AC_CHECK_SIZEOF([long]) -if test "x${ac_cv_sizeof_long}" = "x8" ; then - LG_SIZEOF_LONG=3 -elif test "x${ac_cv_sizeof_long}" = "x4" ; then - LG_SIZEOF_LONG=2 -else - AC_MSG_ERROR([Unsupported long size: ${ac_cv_sizeof_long}]) -fi -AC_DEFINE_UNQUOTED([LG_SIZEOF_LONG], [$LG_SIZEOF_LONG]) - -AC_CHECK_SIZEOF([long long]) -if test "x${ac_cv_sizeof_long_long}" = "x8" ; then - LG_SIZEOF_LONG_LONG=3 -elif test "x${ac_cv_sizeof_long_long}" = "x4" ; then - LG_SIZEOF_LONG_LONG=2 -else - AC_MSG_ERROR([Unsupported long long size: ${ac_cv_sizeof_long_long}]) -fi -AC_DEFINE_UNQUOTED([LG_SIZEOF_LONG_LONG], [$LG_SIZEOF_LONG_LONG]) - -AC_CHECK_SIZEOF([intmax_t]) -if test "x${ac_cv_sizeof_intmax_t}" = "x16" ; then - LG_SIZEOF_INTMAX_T=4 -elif test "x${ac_cv_sizeof_intmax_t}" = "x8" ; then - LG_SIZEOF_INTMAX_T=3 -elif test "x${ac_cv_sizeof_intmax_t}" = "x4" ; then - LG_SIZEOF_INTMAX_T=2 -else - AC_MSG_ERROR([Unsupported intmax_t size: ${ac_cv_sizeof_intmax_t}]) -fi -AC_DEFINE_UNQUOTED([LG_SIZEOF_INTMAX_T], [$LG_SIZEOF_INTMAX_T]) - -AC_CANONICAL_HOST -dnl CPU-specific settings. -CPU_SPINWAIT="" -case "${host_cpu}" in - i686|x86_64) - HAVE_CPU_SPINWAIT=1 - if test "x${je_cv_msvc}" = "xyes" ; then - AC_CACHE_VAL([je_cv_pause_msvc], - [JE_COMPILABLE([pause instruction MSVC], [], - [[_mm_pause(); return 0;]], - [je_cv_pause_msvc])]) - if test "x${je_cv_pause_msvc}" = "xyes" ; then - CPU_SPINWAIT='_mm_pause()' - fi - else - AC_CACHE_VAL([je_cv_pause], - [JE_COMPILABLE([pause instruction], [], - [[__asm__ volatile("pause"); return 0;]], - [je_cv_pause])]) - if test "x${je_cv_pause}" = "xyes" ; then - CPU_SPINWAIT='__asm__ volatile("pause")' - fi - fi - ;; - *) - HAVE_CPU_SPINWAIT=0 - ;; -esac -AC_DEFINE_UNQUOTED([HAVE_CPU_SPINWAIT], [$HAVE_CPU_SPINWAIT]) -AC_DEFINE_UNQUOTED([CPU_SPINWAIT], [$CPU_SPINWAIT]) - -AC_ARG_WITH([lg_vaddr], - [AS_HELP_STRING([--with-lg-vaddr=<lg-vaddr>], [Number of significant virtual address bits])], - [LG_VADDR="$with_lg_vaddr"], [LG_VADDR="detect"]) - -case "${host_cpu}" in - aarch64) - if test "x$LG_VADDR" = "xdetect"; then - AC_MSG_CHECKING([number of significant virtual address bits]) - if test "x${LG_SIZEOF_PTR}" = "x2" ; then - #aarch64 ILP32 - LG_VADDR=32 - else - #aarch64 LP64 - LG_VADDR=48 - fi - AC_MSG_RESULT([$LG_VADDR]) - fi - ;; - x86_64) - if test "x$LG_VADDR" = "xdetect"; then - AC_CACHE_CHECK([number of significant virtual address bits], - [je_cv_lg_vaddr], - AC_RUN_IFELSE([AC_LANG_PROGRAM( -[[ -#include <stdio.h> -#ifdef _WIN32 -#include <limits.h> -#include <intrin.h> -typedef unsigned __int32 uint32_t; -#else -#include <stdint.h> -#endif -]], [[ - uint32_t r[[4]]; - uint32_t eax_in = 0x80000008U; -#ifdef _WIN32 - __cpuid((int *)r, (int)eax_in); -#else - asm volatile ("cpuid" - : "=a" (r[[0]]), "=b" (r[[1]]), "=c" (r[[2]]), "=d" (r[[3]]) - : "a" (eax_in), "c" (0) - ); -#endif - uint32_t eax_out = r[[0]]; - uint32_t vaddr = ((eax_out & 0x0000ff00U) >> 8); - FILE *f = fopen("conftest.out", "w"); - if (f == NULL) { - return 1; - } - if (vaddr > (sizeof(void *) << 3)) { - vaddr = sizeof(void *) << 3; - } - fprintf(f, "%u", vaddr); - fclose(f); - return 0; -]])], - [je_cv_lg_vaddr=`cat conftest.out`], - [je_cv_lg_vaddr=error], - [je_cv_lg_vaddr=57])) - if test "x${je_cv_lg_vaddr}" != "x" ; then - LG_VADDR="${je_cv_lg_vaddr}" - fi - if test "x${LG_VADDR}" != "xerror" ; then - AC_DEFINE_UNQUOTED([LG_VADDR], [$LG_VADDR]) - else - AC_MSG_ERROR([cannot determine number of significant virtual address bits]) - fi - fi - ;; - *) - if test "x$LG_VADDR" = "xdetect"; then - AC_MSG_CHECKING([number of significant virtual address bits]) - if test "x${LG_SIZEOF_PTR}" = "x3" ; then - LG_VADDR=64 - elif test "x${LG_SIZEOF_PTR}" = "x2" ; then - LG_VADDR=32 - elif test "x${LG_SIZEOF_PTR}" = "xLG_SIZEOF_PTR_WIN" ; then - LG_VADDR="(1U << (LG_SIZEOF_PTR_WIN+3))" - else - AC_MSG_ERROR([Unsupported lg(pointer size): ${LG_SIZEOF_PTR}]) - fi - AC_MSG_RESULT([$LG_VADDR]) - fi - ;; -esac -AC_DEFINE_UNQUOTED([LG_VADDR], [$LG_VADDR]) - -LD_PRELOAD_VAR="LD_PRELOAD" -so="so" -importlib="${so}" -o="$ac_objext" -a="a" -exe="$ac_exeext" -libprefix="lib" -link_whole_archive="0" -DSO_LDFLAGS='-shared -Wl,-soname,$(@F)' -RPATH='-Wl,-rpath,$(1)' -SOREV="${so}.${rev}" -PIC_CFLAGS='-fPIC -DPIC' -CTARGET='-o $@' -LDTARGET='-o $@' -TEST_LD_MODE= -EXTRA_LDFLAGS= -ARFLAGS='crus' -AROUT=' $@' -CC_MM=1 - -if test "x$je_cv_cray_prgenv_wrapper" = "xyes" ; then - TEST_LD_MODE='-dynamic' -fi - -if test "x${je_cv_cray}" = "xyes" ; then - CC_MM= -fi - -AN_MAKEVAR([AR], [AC_PROG_AR]) -AN_PROGRAM([ar], [AC_PROG_AR]) -AC_DEFUN([AC_PROG_AR], [AC_CHECK_TOOL(AR, ar, :)]) -AC_PROG_AR - -AN_MAKEVAR([NM], [AC_PROG_NM]) -AN_PROGRAM([nm], [AC_PROG_NM]) -AC_DEFUN([AC_PROG_NM], [AC_CHECK_TOOL(NM, nm, :)]) -AC_PROG_NM - -AC_PROG_AWK - -dnl ============================================================================ -dnl jemalloc version. -dnl - -AC_ARG_WITH([version], - [AS_HELP_STRING([--with-version=<major>.<minor>.<bugfix>-<nrev>-g<gid>], - [Version string])], - [ - echo "${with_version}" | grep ['^[0-9]\+\.[0-9]\+\.[0-9]\+-[0-9]\+-g[0-9a-f]\+$'] 2>&1 1>/dev/null - if test $? -eq 0 ; then - echo "$with_version" > "${objroot}VERSION" - else - echo "${with_version}" | grep ['^VERSION$'] 2>&1 1>/dev/null - if test $? -ne 0 ; then - AC_MSG_ERROR([${with_version} does not match <major>.<minor>.<bugfix>-<nrev>-g<gid> or VERSION]) - fi - fi - ], [ - dnl Set VERSION if source directory is inside a git repository. - if test "x`test ! \"${srcroot}\" && cd \"${srcroot}\"; git rev-parse --is-inside-work-tree 2>/dev/null`" = "xtrue" ; then - dnl Pattern globs aren't powerful enough to match both single- and - dnl double-digit version numbers, so iterate over patterns to support up - dnl to version 99.99.99 without any accidental matches. - for pattern in ['[0-9].[0-9].[0-9]' '[0-9].[0-9].[0-9][0-9]' \ - '[0-9].[0-9][0-9].[0-9]' '[0-9].[0-9][0-9].[0-9][0-9]' \ - '[0-9][0-9].[0-9].[0-9]' '[0-9][0-9].[0-9].[0-9][0-9]' \ - '[0-9][0-9].[0-9][0-9].[0-9]' \ - '[0-9][0-9].[0-9][0-9].[0-9][0-9]']; do - (test ! "${srcroot}" && cd "${srcroot}"; git describe --long --abbrev=40 --match="${pattern}") > "${objroot}VERSION.tmp" 2>/dev/null - if test $? -eq 0 ; then - mv "${objroot}VERSION.tmp" "${objroot}VERSION" - break - fi - done - fi - rm -f "${objroot}VERSION.tmp" - ]) - -if test ! -e "${objroot}VERSION" ; then - if test ! -e "${srcroot}VERSION" ; then - AC_MSG_RESULT( - [Missing VERSION file, and unable to generate it; creating bogus VERSION]) - echo "0.0.0-0-g0000000000000000000000000000000000000000" > "${objroot}VERSION" - else - cp ${srcroot}VERSION ${objroot}VERSION - fi -fi -jemalloc_version=`cat "${objroot}VERSION"` -jemalloc_version_major=`echo ${jemalloc_version} | tr ".g-" " " | awk '{print [$]1}'` -jemalloc_version_minor=`echo ${jemalloc_version} | tr ".g-" " " | awk '{print [$]2}'` -jemalloc_version_bugfix=`echo ${jemalloc_version} | tr ".g-" " " | awk '{print [$]3}'` -jemalloc_version_nrev=`echo ${jemalloc_version} | tr ".g-" " " | awk '{print [$]4}'` -jemalloc_version_gid=`echo ${jemalloc_version} | tr ".g-" " " | awk '{print [$]5}'` -AC_SUBST([jemalloc_version]) -AC_SUBST([jemalloc_version_major]) -AC_SUBST([jemalloc_version_minor]) -AC_SUBST([jemalloc_version_bugfix]) -AC_SUBST([jemalloc_version_nrev]) -AC_SUBST([jemalloc_version_gid]) - -dnl Platform-specific settings. abi and RPATH can probably be determined -dnl programmatically, but doing so is error-prone, which makes it generally -dnl not worth the trouble. -dnl -dnl Define cpp macros in CPPFLAGS, rather than doing AC_DEFINE(macro), since the -dnl definitions need to be seen before any headers are included, which is a pain -dnl to make happen otherwise. -default_retain="0" -maps_coalesce="1" -DUMP_SYMS="${NM} -a" -SYM_PREFIX="" -case "${host}" in - *-*-darwin* | *-*-ios*) - abi="macho" - RPATH="" - LD_PRELOAD_VAR="DYLD_INSERT_LIBRARIES" - so="dylib" - importlib="${so}" - force_tls="0" - DSO_LDFLAGS='-shared -Wl,-install_name,$(LIBDIR)/$(@F)' - SOREV="${rev}.${so}" - sbrk_deprecated="1" - SYM_PREFIX="_" - ;; - *-*-freebsd*) - abi="elf" - AC_DEFINE([JEMALLOC_SYSCTL_VM_OVERCOMMIT], [ ]) - force_lazy_lock="1" - ;; - *-*-dragonfly*) - abi="elf" - ;; - *-*-openbsd*) - abi="elf" - force_tls="0" - ;; - *-*-bitrig*) - abi="elf" - ;; - *-*-linux-android) - dnl syscall(2) and secure_getenv(3) are exposed by _GNU_SOURCE. - JE_APPEND_VS(CPPFLAGS, -D_GNU_SOURCE) - abi="elf" - AC_DEFINE([JEMALLOC_PURGE_MADVISE_DONTNEED_ZEROS], [ ]) - AC_DEFINE([JEMALLOC_HAS_ALLOCA_H]) - AC_DEFINE([JEMALLOC_PROC_SYS_VM_OVERCOMMIT_MEMORY], [ ]) - AC_DEFINE([JEMALLOC_THREADED_INIT], [ ]) - AC_DEFINE([JEMALLOC_C11_ATOMICS]) - force_tls="0" - if test "${LG_SIZEOF_PTR}" = "3"; then - default_retain="1" - fi - ;; - *-*-linux*) - dnl syscall(2) and secure_getenv(3) are exposed by _GNU_SOURCE. - JE_APPEND_VS(CPPFLAGS, -D_GNU_SOURCE) - abi="elf" - AC_DEFINE([JEMALLOC_PURGE_MADVISE_DONTNEED_ZEROS], [ ]) - AC_DEFINE([JEMALLOC_HAS_ALLOCA_H]) - AC_DEFINE([JEMALLOC_PROC_SYS_VM_OVERCOMMIT_MEMORY], [ ]) - AC_DEFINE([JEMALLOC_THREADED_INIT], [ ]) - AC_DEFINE([JEMALLOC_USE_CXX_THROW], [ ]) - if test "${LG_SIZEOF_PTR}" = "3"; then - default_retain="1" - fi - ;; - *-*-kfreebsd*) - dnl syscall(2) and secure_getenv(3) are exposed by _GNU_SOURCE. - JE_APPEND_VS(CPPFLAGS, -D_GNU_SOURCE) - abi="elf" - AC_DEFINE([JEMALLOC_HAS_ALLOCA_H]) - AC_DEFINE([JEMALLOC_SYSCTL_VM_OVERCOMMIT], [ ]) - AC_DEFINE([JEMALLOC_THREADED_INIT], [ ]) - AC_DEFINE([JEMALLOC_USE_CXX_THROW], [ ]) - ;; - *-*-netbsd*) - AC_MSG_CHECKING([ABI]) - AC_COMPILE_IFELSE([AC_LANG_PROGRAM( -[[#ifdef __ELF__ -/* ELF */ -#else -#error aout -#endif -]])], - [abi="elf"], - [abi="aout"]) - AC_MSG_RESULT([$abi]) - ;; - *-*-solaris2*) - abi="elf" - RPATH='-Wl,-R,$(1)' - dnl Solaris needs this for sigwait(). - JE_APPEND_VS(CPPFLAGS, -D_POSIX_PTHREAD_SEMANTICS) - JE_APPEND_VS(LIBS, -lposix4 -lsocket -lnsl) - ;; - *-ibm-aix*) - if test "${LG_SIZEOF_PTR}" = "3"; then - dnl 64bit AIX - LD_PRELOAD_VAR="LDR_PRELOAD64" - else - dnl 32bit AIX - LD_PRELOAD_VAR="LDR_PRELOAD" - fi - abi="xcoff" - ;; - *-*-mingw* | *-*-cygwin*) - abi="pecoff" - force_tls="0" - maps_coalesce="0" - RPATH="" - so="dll" - if test "x$je_cv_msvc" = "xyes" ; then - importlib="lib" - DSO_LDFLAGS="-LD" - EXTRA_LDFLAGS="-link -DEBUG" - CTARGET='-Fo$@' - LDTARGET='-Fe$@' - AR='lib' - ARFLAGS='-nologo -out:' - AROUT='$@' - CC_MM= - else - importlib="${so}" - DSO_LDFLAGS="-shared" - link_whole_archive="1" - fi - case "${host}" in - *-*-cygwin*) - DUMP_SYMS="dumpbin /SYMBOLS" - ;; - *) - ;; - esac - a="lib" - libprefix="" - SOREV="${so}" - PIC_CFLAGS="" - if test "${LG_SIZEOF_PTR}" = "3"; then - default_retain="1" - fi - ;; - *) - AC_MSG_RESULT([Unsupported operating system: ${host}]) - abi="elf" - ;; -esac - -JEMALLOC_USABLE_SIZE_CONST=const -AC_CHECK_HEADERS([malloc.h], [ - AC_MSG_CHECKING([whether malloc_usable_size definition can use const argument]) - AC_COMPILE_IFELSE([AC_LANG_PROGRAM( - [#include <malloc.h> - #include <stddef.h> - size_t malloc_usable_size(const void *ptr); - ], - [])],[ - AC_MSG_RESULT([yes]) - ],[ - JEMALLOC_USABLE_SIZE_CONST= - AC_MSG_RESULT([no]) - ]) -]) -AC_DEFINE_UNQUOTED([JEMALLOC_USABLE_SIZE_CONST], [$JEMALLOC_USABLE_SIZE_CONST]) -AC_SUBST([abi]) -AC_SUBST([RPATH]) -AC_SUBST([LD_PRELOAD_VAR]) -AC_SUBST([so]) -AC_SUBST([importlib]) -AC_SUBST([o]) -AC_SUBST([a]) -AC_SUBST([exe]) -AC_SUBST([libprefix]) -AC_SUBST([link_whole_archive]) -AC_SUBST([DSO_LDFLAGS]) -AC_SUBST([EXTRA_LDFLAGS]) -AC_SUBST([SOREV]) -AC_SUBST([PIC_CFLAGS]) -AC_SUBST([CTARGET]) -AC_SUBST([LDTARGET]) -AC_SUBST([TEST_LD_MODE]) -AC_SUBST([MKLIB]) -AC_SUBST([ARFLAGS]) -AC_SUBST([AROUT]) -AC_SUBST([DUMP_SYMS]) -AC_SUBST([CC_MM]) - -dnl Determine whether libm must be linked to use e.g. log(3). -AC_SEARCH_LIBS([log], [m], , [AC_MSG_ERROR([Missing math functions])]) -if test "x$ac_cv_search_log" != "xnone required" ; then - LM="$ac_cv_search_log" -else - LM= -fi -AC_SUBST(LM) - -JE_COMPILABLE([__attribute__ syntax], - [static __attribute__((unused)) void foo(void){}], - [], - [je_cv_attribute]) -if test "x${je_cv_attribute}" = "xyes" ; then - AC_DEFINE([JEMALLOC_HAVE_ATTR], [ ]) - if test "x${GCC}" = "xyes" -a "x${abi}" = "xelf"; then - JE_CFLAGS_ADD([-fvisibility=hidden]) - JE_CXXFLAGS_ADD([-fvisibility=hidden]) - fi -fi -dnl Check for tls_model attribute support (clang 3.0 still lacks support). -JE_CFLAGS_SAVE() -JE_CFLAGS_ADD([-Werror]) -JE_CFLAGS_ADD([-herror_on_warning]) -JE_COMPILABLE([tls_model attribute], [], - [static __thread int - __attribute__((tls_model("initial-exec"), unused)) foo; - foo = 0;], - [je_cv_tls_model]) -JE_CFLAGS_RESTORE() -dnl (Setting of JEMALLOC_TLS_MODEL is done later, after we've checked for -dnl --disable-initial-exec-tls) - -dnl Check for alloc_size attribute support. -JE_CFLAGS_SAVE() -JE_CFLAGS_ADD([-Werror]) -JE_CFLAGS_ADD([-herror_on_warning]) -JE_COMPILABLE([alloc_size attribute], [#include <stdlib.h>], - [void *foo(size_t size) __attribute__((alloc_size(1)));], - [je_cv_alloc_size]) -JE_CFLAGS_RESTORE() -if test "x${je_cv_alloc_size}" = "xyes" ; then - AC_DEFINE([JEMALLOC_HAVE_ATTR_ALLOC_SIZE], [ ]) -fi -dnl Check for format(gnu_printf, ...) attribute support. -JE_CFLAGS_SAVE() -JE_CFLAGS_ADD([-Werror]) -JE_CFLAGS_ADD([-herror_on_warning]) -JE_COMPILABLE([format(gnu_printf, ...) attribute], [#include <stdlib.h>], - [void *foo(const char *format, ...) __attribute__((format(gnu_printf, 1, 2)));], - [je_cv_format_gnu_printf]) -JE_CFLAGS_RESTORE() -if test "x${je_cv_format_gnu_printf}" = "xyes" ; then - AC_DEFINE([JEMALLOC_HAVE_ATTR_FORMAT_GNU_PRINTF], [ ]) -fi -dnl Check for format(printf, ...) attribute support. -JE_CFLAGS_SAVE() -JE_CFLAGS_ADD([-Werror]) -JE_CFLAGS_ADD([-herror_on_warning]) -JE_COMPILABLE([format(printf, ...) attribute], [#include <stdlib.h>], - [void *foo(const char *format, ...) __attribute__((format(printf, 1, 2)));], - [je_cv_format_printf]) -JE_CFLAGS_RESTORE() -if test "x${je_cv_format_printf}" = "xyes" ; then - AC_DEFINE([JEMALLOC_HAVE_ATTR_FORMAT_PRINTF], [ ]) -fi - -dnl Check for format_arg(...) attribute support. -JE_CFLAGS_SAVE() -JE_CFLAGS_ADD([-Werror]) -JE_CFLAGS_ADD([-herror_on_warning]) -JE_COMPILABLE([format(printf, ...) attribute], [#include <stdlib.h>], - [const char * __attribute__((__format_arg__(1))) foo(const char *format);], - [je_cv_format_arg]) -JE_CFLAGS_RESTORE() -if test "x${je_cv_format_arg}" = "xyes" ; then - AC_DEFINE([JEMALLOC_HAVE_ATTR_FORMAT_ARG], [ ]) -fi - -dnl Support optional additions to rpath. -AC_ARG_WITH([rpath], - [AS_HELP_STRING([--with-rpath=<rpath>], [Colon-separated rpath (ELF systems only)])], -if test "x$with_rpath" = "xno" ; then - RPATH_EXTRA= -else - RPATH_EXTRA="`echo $with_rpath | tr \":\" \" \"`" -fi, - RPATH_EXTRA= -) -AC_SUBST([RPATH_EXTRA]) - -dnl Disable rules that do automatic regeneration of configure output by default. -AC_ARG_ENABLE([autogen], - [AS_HELP_STRING([--enable-autogen], [Automatically regenerate configure output])], -if test "x$enable_autogen" = "xno" ; then - enable_autogen="0" -else - enable_autogen="1" -fi -, -enable_autogen="0" -) -AC_SUBST([enable_autogen]) - -AC_PROG_INSTALL -AC_PROG_RANLIB -AC_PATH_PROG([LD], [ld], [false], [$PATH]) -AC_PATH_PROG([AUTOCONF], [autoconf], [false], [$PATH]) - -dnl Enable documentation -AC_ARG_ENABLE([doc], - [AS_HELP_STRING([--enable-documentation], [Build documentation])], -if test "x$enable_doc" = "xno" ; then - enable_doc="0" -else - enable_doc="1" -fi -, -enable_doc="1" -) -AC_SUBST([enable_doc]) - -dnl Enable shared libs -AC_ARG_ENABLE([shared], - [AS_HELP_STRING([--enable-shared], [Build shared libaries])], -if test "x$enable_shared" = "xno" ; then - enable_shared="0" -else - enable_shared="1" -fi -, -enable_shared="1" -) -AC_SUBST([enable_shared]) - -dnl Enable static libs -AC_ARG_ENABLE([static], - [AS_HELP_STRING([--enable-static], [Build static libaries])], -if test "x$enable_static" = "xno" ; then - enable_static="0" -else - enable_static="1" -fi -, -enable_static="1" -) -AC_SUBST([enable_static]) - -if test "$enable_shared$enable_static" = "00" ; then - AC_MSG_ERROR([Please enable one of shared or static builds]) -fi - -dnl Perform no name mangling by default. -AC_ARG_WITH([mangling], - [AS_HELP_STRING([--with-mangling=<map>], [Mangle symbols in <map>])], - [mangling_map="$with_mangling"], [mangling_map=""]) - -dnl Do not prefix public APIs by default. -AC_ARG_WITH([jemalloc_prefix], - [AS_HELP_STRING([--with-jemalloc-prefix=<prefix>], [Prefix to prepend to all public APIs])], - [JEMALLOC_PREFIX="$with_jemalloc_prefix"], - [if test "x$abi" != "xmacho" -a "x$abi" != "xpecoff"; then - JEMALLOC_PREFIX="" -else - JEMALLOC_PREFIX="je_" -fi] -) -if test "x$JEMALLOC_PREFIX" = "x" ; then - AC_DEFINE([JEMALLOC_IS_MALLOC]) -else - JEMALLOC_CPREFIX=`echo ${JEMALLOC_PREFIX} | tr "a-z" "A-Z"` - AC_DEFINE_UNQUOTED([JEMALLOC_PREFIX], ["$JEMALLOC_PREFIX"]) - AC_DEFINE_UNQUOTED([JEMALLOC_CPREFIX], ["$JEMALLOC_CPREFIX"]) -fi -AC_SUBST([JEMALLOC_PREFIX]) -AC_SUBST([JEMALLOC_CPREFIX]) - -AC_ARG_WITH([export], - [AS_HELP_STRING([--without-export], [disable exporting jemalloc public APIs])], - [if test "x$with_export" = "xno"; then - AC_DEFINE([JEMALLOC_EXPORT],[]) -fi] -) - -public_syms="aligned_alloc calloc dallocx free mallctl mallctlbymib mallctlnametomib malloc malloc_conf malloc_message malloc_stats_print malloc_usable_size mallocx smallocx_${jemalloc_version_gid} nallocx posix_memalign rallocx realloc sallocx sdallocx xallocx" -dnl Check for additional platform-specific public API functions. -AC_CHECK_FUNC([memalign], - [AC_DEFINE([JEMALLOC_OVERRIDE_MEMALIGN], [ ]) - public_syms="${public_syms} memalign"]) -AC_CHECK_FUNC([valloc], - [AC_DEFINE([JEMALLOC_OVERRIDE_VALLOC], [ ]) - public_syms="${public_syms} valloc"]) - -dnl Check for allocator-related functions that should be wrapped. -wrap_syms= -if test "x${JEMALLOC_PREFIX}" = "x" ; then - AC_CHECK_FUNC([__libc_calloc], - [AC_DEFINE([JEMALLOC_OVERRIDE___LIBC_CALLOC], [ ]) - wrap_syms="${wrap_syms} __libc_calloc"]) - AC_CHECK_FUNC([__libc_free], - [AC_DEFINE([JEMALLOC_OVERRIDE___LIBC_FREE], [ ]) - wrap_syms="${wrap_syms} __libc_free"]) - AC_CHECK_FUNC([__libc_malloc], - [AC_DEFINE([JEMALLOC_OVERRIDE___LIBC_MALLOC], [ ]) - wrap_syms="${wrap_syms} __libc_malloc"]) - AC_CHECK_FUNC([__libc_memalign], - [AC_DEFINE([JEMALLOC_OVERRIDE___LIBC_MEMALIGN], [ ]) - wrap_syms="${wrap_syms} __libc_memalign"]) - AC_CHECK_FUNC([__libc_realloc], - [AC_DEFINE([JEMALLOC_OVERRIDE___LIBC_REALLOC], [ ]) - wrap_syms="${wrap_syms} __libc_realloc"]) - AC_CHECK_FUNC([__libc_valloc], - [AC_DEFINE([JEMALLOC_OVERRIDE___LIBC_VALLOC], [ ]) - wrap_syms="${wrap_syms} __libc_valloc"]) - AC_CHECK_FUNC([__posix_memalign], - [AC_DEFINE([JEMALLOC_OVERRIDE___POSIX_MEMALIGN], [ ]) - wrap_syms="${wrap_syms} __posix_memalign"]) -fi - -case "${host}" in - *-*-mingw* | *-*-cygwin*) - wrap_syms="${wrap_syms} tls_callback" - ;; - *) - ;; -esac - -dnl Mangle library-private APIs. -AC_ARG_WITH([private_namespace], - [AS_HELP_STRING([--with-private-namespace=<prefix>], [Prefix to prepend to all library-private APIs])], - [JEMALLOC_PRIVATE_NAMESPACE="${with_private_namespace}je_"], - [JEMALLOC_PRIVATE_NAMESPACE="je_"] -) -AC_DEFINE_UNQUOTED([JEMALLOC_PRIVATE_NAMESPACE], [$JEMALLOC_PRIVATE_NAMESPACE]) -private_namespace="$JEMALLOC_PRIVATE_NAMESPACE" -AC_SUBST([private_namespace]) - -dnl Do not add suffix to installed files by default. -AC_ARG_WITH([install_suffix], - [AS_HELP_STRING([--with-install-suffix=<suffix>], [Suffix to append to all installed files])], - [INSTALL_SUFFIX="$with_install_suffix"], - [INSTALL_SUFFIX=] -) -install_suffix="$INSTALL_SUFFIX" -AC_SUBST([install_suffix]) - -dnl Specify default malloc_conf. -AC_ARG_WITH([malloc_conf], - [AS_HELP_STRING([--with-malloc-conf=<malloc_conf>], [config.malloc_conf options string])], - [JEMALLOC_CONFIG_MALLOC_CONF="$with_malloc_conf"], - [JEMALLOC_CONFIG_MALLOC_CONF=""] -) -config_malloc_conf="$JEMALLOC_CONFIG_MALLOC_CONF" -AC_DEFINE_UNQUOTED([JEMALLOC_CONFIG_MALLOC_CONF], ["$config_malloc_conf"]) - -dnl Substitute @je_@ in jemalloc_protos.h.in, primarily to make generation of -dnl jemalloc_protos_jet.h easy. -je_="je_" -AC_SUBST([je_]) - -cfgoutputs_in="Makefile.in" -cfgoutputs_in="${cfgoutputs_in} jemalloc.pc.in" -cfgoutputs_in="${cfgoutputs_in} doc/html.xsl.in" -cfgoutputs_in="${cfgoutputs_in} doc/manpages.xsl.in" -cfgoutputs_in="${cfgoutputs_in} doc/jemalloc.xml.in" -cfgoutputs_in="${cfgoutputs_in} include/jemalloc/jemalloc_macros.h.in" -cfgoutputs_in="${cfgoutputs_in} include/jemalloc/jemalloc_protos.h.in" -cfgoutputs_in="${cfgoutputs_in} include/jemalloc/jemalloc_typedefs.h.in" -cfgoutputs_in="${cfgoutputs_in} include/jemalloc/internal/jemalloc_preamble.h.in" -cfgoutputs_in="${cfgoutputs_in} test/test.sh.in" -cfgoutputs_in="${cfgoutputs_in} test/include/test/jemalloc_test.h.in" - -cfgoutputs_out="Makefile" -cfgoutputs_out="${cfgoutputs_out} jemalloc.pc" -cfgoutputs_out="${cfgoutputs_out} doc/html.xsl" -cfgoutputs_out="${cfgoutputs_out} doc/manpages.xsl" -cfgoutputs_out="${cfgoutputs_out} doc/jemalloc.xml" -cfgoutputs_out="${cfgoutputs_out} include/jemalloc/jemalloc_macros.h" -cfgoutputs_out="${cfgoutputs_out} include/jemalloc/jemalloc_protos.h" -cfgoutputs_out="${cfgoutputs_out} include/jemalloc/jemalloc_typedefs.h" -cfgoutputs_out="${cfgoutputs_out} include/jemalloc/internal/jemalloc_preamble.h" -cfgoutputs_out="${cfgoutputs_out} test/test.sh" -cfgoutputs_out="${cfgoutputs_out} test/include/test/jemalloc_test.h" - -cfgoutputs_tup="Makefile" -cfgoutputs_tup="${cfgoutputs_tup} jemalloc.pc:jemalloc.pc.in" -cfgoutputs_tup="${cfgoutputs_tup} doc/html.xsl:doc/html.xsl.in" -cfgoutputs_tup="${cfgoutputs_tup} doc/manpages.xsl:doc/manpages.xsl.in" -cfgoutputs_tup="${cfgoutputs_tup} doc/jemalloc.xml:doc/jemalloc.xml.in" -cfgoutputs_tup="${cfgoutputs_tup} include/jemalloc/jemalloc_macros.h:include/jemalloc/jemalloc_macros.h.in" -cfgoutputs_tup="${cfgoutputs_tup} include/jemalloc/jemalloc_protos.h:include/jemalloc/jemalloc_protos.h.in" -cfgoutputs_tup="${cfgoutputs_tup} include/jemalloc/jemalloc_typedefs.h:include/jemalloc/jemalloc_typedefs.h.in" -cfgoutputs_tup="${cfgoutputs_tup} include/jemalloc/internal/jemalloc_preamble.h" -cfgoutputs_tup="${cfgoutputs_tup} test/test.sh:test/test.sh.in" -cfgoutputs_tup="${cfgoutputs_tup} test/include/test/jemalloc_test.h:test/include/test/jemalloc_test.h.in" - -cfghdrs_in="include/jemalloc/jemalloc_defs.h.in" -cfghdrs_in="${cfghdrs_in} include/jemalloc/internal/jemalloc_internal_defs.h.in" -cfghdrs_in="${cfghdrs_in} include/jemalloc/internal/private_symbols.sh" -cfghdrs_in="${cfghdrs_in} include/jemalloc/internal/private_namespace.sh" -cfghdrs_in="${cfghdrs_in} include/jemalloc/internal/public_namespace.sh" -cfghdrs_in="${cfghdrs_in} include/jemalloc/internal/public_unnamespace.sh" -cfghdrs_in="${cfghdrs_in} include/jemalloc/jemalloc_rename.sh" -cfghdrs_in="${cfghdrs_in} include/jemalloc/jemalloc_mangle.sh" -cfghdrs_in="${cfghdrs_in} include/jemalloc/jemalloc.sh" -cfghdrs_in="${cfghdrs_in} test/include/test/jemalloc_test_defs.h.in" - -cfghdrs_out="include/jemalloc/jemalloc_defs.h" -cfghdrs_out="${cfghdrs_out} include/jemalloc/jemalloc${install_suffix}.h" -cfghdrs_out="${cfghdrs_out} include/jemalloc/internal/private_symbols.awk" -cfghdrs_out="${cfghdrs_out} include/jemalloc/internal/private_symbols_jet.awk" -cfghdrs_out="${cfghdrs_out} include/jemalloc/internal/public_symbols.txt" -cfghdrs_out="${cfghdrs_out} include/jemalloc/internal/public_namespace.h" -cfghdrs_out="${cfghdrs_out} include/jemalloc/internal/public_unnamespace.h" -cfghdrs_out="${cfghdrs_out} include/jemalloc/jemalloc_protos_jet.h" -cfghdrs_out="${cfghdrs_out} include/jemalloc/jemalloc_rename.h" -cfghdrs_out="${cfghdrs_out} include/jemalloc/jemalloc_mangle.h" -cfghdrs_out="${cfghdrs_out} include/jemalloc/jemalloc_mangle_jet.h" -cfghdrs_out="${cfghdrs_out} include/jemalloc/internal/jemalloc_internal_defs.h" -cfghdrs_out="${cfghdrs_out} test/include/test/jemalloc_test_defs.h" - -cfghdrs_tup="include/jemalloc/jemalloc_defs.h:include/jemalloc/jemalloc_defs.h.in" -cfghdrs_tup="${cfghdrs_tup} include/jemalloc/internal/jemalloc_internal_defs.h:include/jemalloc/internal/jemalloc_internal_defs.h.in" -cfghdrs_tup="${cfghdrs_tup} test/include/test/jemalloc_test_defs.h:test/include/test/jemalloc_test_defs.h.in" - -dnl ============================================================================ -dnl jemalloc build options. -dnl - -dnl Do not compile with debugging by default. -AC_ARG_ENABLE([debug], - [AS_HELP_STRING([--enable-debug], - [Build debugging code])], -[if test "x$enable_debug" = "xno" ; then - enable_debug="0" -else - enable_debug="1" -fi -], -[enable_debug="0"] -) -if test "x$enable_debug" = "x1" ; then - AC_DEFINE([JEMALLOC_DEBUG], [ ]) -fi -if test "x$enable_debug" = "x1" ; then - AC_DEFINE([JEMALLOC_DEBUG], [ ]) -fi -AC_SUBST([enable_debug]) - -dnl Only optimize if not debugging. -if test "x$enable_debug" = "x0" ; then - if test "x$GCC" = "xyes" ; then - JE_CFLAGS_ADD([-O3]) - JE_CXXFLAGS_ADD([-O3]) - JE_CFLAGS_ADD([-funroll-loops]) - elif test "x$je_cv_msvc" = "xyes" ; then - JE_CFLAGS_ADD([-O2]) - JE_CXXFLAGS_ADD([-O2]) - else - JE_CFLAGS_ADD([-O]) - JE_CXXFLAGS_ADD([-O]) - fi -fi - -dnl Enable statistics calculation by default. -AC_ARG_ENABLE([stats], - [AS_HELP_STRING([--disable-stats], - [Disable statistics calculation/reporting])], -[if test "x$enable_stats" = "xno" ; then - enable_stats="0" -else - enable_stats="1" -fi -], -[enable_stats="1"] -) -if test "x$enable_stats" = "x1" ; then - AC_DEFINE([JEMALLOC_STATS], [ ]) -fi -AC_SUBST([enable_stats]) - -dnl Do not enable smallocx by default. -AC_ARG_ENABLE([experimental_smallocx], - [AS_HELP_STRING([--enable-experimental-smallocx], [Enable experimental smallocx API])], -[if test "x$enable_experimental_smallocx" = "xno" ; then -enable_experimental_smallocx="0" -else -enable_experimental_smallocx="1" -fi -], -[enable_experimental_smallocx="0"] -) -if test "x$enable_experimental_smallocx" = "x1" ; then - AC_DEFINE([JEMALLOC_EXPERIMENTAL_SMALLOCX_API]) -fi -AC_SUBST([enable_experimental_smallocx]) - -dnl Do not enable profiling by default. -AC_ARG_ENABLE([prof], - [AS_HELP_STRING([--enable-prof], [Enable allocation profiling])], -[if test "x$enable_prof" = "xno" ; then - enable_prof="0" -else - enable_prof="1" -fi -], -[enable_prof="0"] -) -if test "x$enable_prof" = "x1" ; then - backtrace_method="" -else - backtrace_method="N/A" -fi - -AC_ARG_ENABLE([prof-libunwind], - [AS_HELP_STRING([--enable-prof-libunwind], [Use libunwind for backtracing])], -[if test "x$enable_prof_libunwind" = "xno" ; then - enable_prof_libunwind="0" -else - enable_prof_libunwind="1" -fi -], -[enable_prof_libunwind="0"] -) -AC_ARG_WITH([static_libunwind], - [AS_HELP_STRING([--with-static-libunwind=<libunwind.a>], - [Path to static libunwind library; use rather than dynamically linking])], -if test "x$with_static_libunwind" = "xno" ; then - LUNWIND="-lunwind" -else - if test ! -f "$with_static_libunwind" ; then - AC_MSG_ERROR([Static libunwind not found: $with_static_libunwind]) - fi - LUNWIND="$with_static_libunwind" -fi, - LUNWIND="-lunwind" -) -if test "x$backtrace_method" = "x" -a "x$enable_prof_libunwind" = "x1" ; then - AC_CHECK_HEADERS([libunwind.h], , [enable_prof_libunwind="0"]) - if test "x$LUNWIND" = "x-lunwind" ; then - AC_CHECK_LIB([unwind], [unw_backtrace], [JE_APPEND_VS(LIBS, $LUNWIND)], - [enable_prof_libunwind="0"]) - else - JE_APPEND_VS(LIBS, $LUNWIND) - fi - if test "x${enable_prof_libunwind}" = "x1" ; then - backtrace_method="libunwind" - AC_DEFINE([JEMALLOC_PROF_LIBUNWIND], [ ]) - fi -fi - -AC_ARG_ENABLE([prof-libgcc], - [AS_HELP_STRING([--disable-prof-libgcc], - [Do not use libgcc for backtracing])], -[if test "x$enable_prof_libgcc" = "xno" ; then - enable_prof_libgcc="0" -else - enable_prof_libgcc="1" -fi -], -[enable_prof_libgcc="1"] -) -if test "x$backtrace_method" = "x" -a "x$enable_prof_libgcc" = "x1" \ - -a "x$GCC" = "xyes" ; then - AC_CHECK_HEADERS([unwind.h], , [enable_prof_libgcc="0"]) - if test "x${enable_prof_libgcc}" = "x1" ; then - AC_CHECK_LIB([gcc], [_Unwind_Backtrace], [JE_APPEND_VS(LIBS, -lgcc)], [enable_prof_libgcc="0"]) - fi - if test "x${enable_prof_libgcc}" = "x1" ; then - backtrace_method="libgcc" - AC_DEFINE([JEMALLOC_PROF_LIBGCC], [ ]) - fi -else - enable_prof_libgcc="0" -fi - -AC_ARG_ENABLE([prof-gcc], - [AS_HELP_STRING([--disable-prof-gcc], - [Do not use gcc intrinsics for backtracing])], -[if test "x$enable_prof_gcc" = "xno" ; then - enable_prof_gcc="0" -else - enable_prof_gcc="1" -fi -], -[enable_prof_gcc="1"] -) -if test "x$backtrace_method" = "x" -a "x$enable_prof_gcc" = "x1" \ - -a "x$GCC" = "xyes" ; then - JE_CFLAGS_ADD([-fno-omit-frame-pointer]) - backtrace_method="gcc intrinsics" - AC_DEFINE([JEMALLOC_PROF_GCC], [ ]) -else - enable_prof_gcc="0" -fi - -if test "x$backtrace_method" = "x" ; then - backtrace_method="none (disabling profiling)" - enable_prof="0" -fi -AC_MSG_CHECKING([configured backtracing method]) -AC_MSG_RESULT([$backtrace_method]) -if test "x$enable_prof" = "x1" ; then - dnl Heap profiling uses the log(3) function. - JE_APPEND_VS(LIBS, $LM) - - AC_DEFINE([JEMALLOC_PROF], [ ]) -fi -AC_SUBST([enable_prof]) - -dnl Indicate whether adjacent virtual memory mappings automatically coalesce -dnl (and fragment on demand). -if test "x${maps_coalesce}" = "x1" ; then - AC_DEFINE([JEMALLOC_MAPS_COALESCE], [ ]) -fi - -dnl Indicate whether to retain memory (rather than using munmap()) by default. -if test "x$default_retain" = "x1" ; then - AC_DEFINE([JEMALLOC_RETAIN], [ ]) -fi - -dnl Enable allocation from DSS if supported by the OS. -have_dss="1" -dnl Check whether the BSD/SUSv1 sbrk() exists. If not, disable DSS support. -AC_CHECK_FUNC([sbrk], [have_sbrk="1"], [have_sbrk="0"]) -if test "x$have_sbrk" = "x1" ; then - if test "x$sbrk_deprecated" = "x1" ; then - AC_MSG_RESULT([Disabling dss allocation because sbrk is deprecated]) - have_dss="0" - fi -else - have_dss="0" -fi - -if test "x$have_dss" = "x1" ; then - AC_DEFINE([JEMALLOC_DSS], [ ]) -fi - -dnl Support the junk/zero filling option by default. -AC_ARG_ENABLE([fill], - [AS_HELP_STRING([--disable-fill], [Disable support for junk/zero filling])], -[if test "x$enable_fill" = "xno" ; then - enable_fill="0" -else - enable_fill="1" -fi -], -[enable_fill="1"] -) -if test "x$enable_fill" = "x1" ; then - AC_DEFINE([JEMALLOC_FILL], [ ]) -fi -AC_SUBST([enable_fill]) - -dnl Disable utrace(2)-based tracing by default. -AC_ARG_ENABLE([utrace], - [AS_HELP_STRING([--enable-utrace], [Enable utrace(2)-based tracing])], -[if test "x$enable_utrace" = "xno" ; then - enable_utrace="0" -else - enable_utrace="1" -fi -], -[enable_utrace="0"] -) -JE_COMPILABLE([utrace(2)], [ -#include <sys/types.h> -#include <sys/param.h> -#include <sys/time.h> -#include <sys/uio.h> -#include <sys/ktrace.h> -], [ - utrace((void *)0, 0); -], [je_cv_utrace]) -if test "x${je_cv_utrace}" = "xno" ; then - enable_utrace="0" -fi -if test "x$enable_utrace" = "x1" ; then - AC_DEFINE([JEMALLOC_UTRACE], [ ]) -fi -AC_SUBST([enable_utrace]) - -dnl Do not support the xmalloc option by default. -AC_ARG_ENABLE([xmalloc], - [AS_HELP_STRING([--enable-xmalloc], [Support xmalloc option])], -[if test "x$enable_xmalloc" = "xno" ; then - enable_xmalloc="0" -else - enable_xmalloc="1" -fi -], -[enable_xmalloc="0"] -) -if test "x$enable_xmalloc" = "x1" ; then - AC_DEFINE([JEMALLOC_XMALLOC], [ ]) -fi -AC_SUBST([enable_xmalloc]) - -dnl Support cache-oblivious allocation alignment by default. -AC_ARG_ENABLE([cache-oblivious], - [AS_HELP_STRING([--disable-cache-oblivious], - [Disable support for cache-oblivious allocation alignment])], -[if test "x$enable_cache_oblivious" = "xno" ; then - enable_cache_oblivious="0" -else - enable_cache_oblivious="1" -fi -], -[enable_cache_oblivious="1"] -) -if test "x$enable_cache_oblivious" = "x1" ; then - AC_DEFINE([JEMALLOC_CACHE_OBLIVIOUS], [ ]) -fi -AC_SUBST([enable_cache_oblivious]) - -dnl Do not log by default. -AC_ARG_ENABLE([log], - [AS_HELP_STRING([--enable-log], [Support debug logging])], -[if test "x$enable_log" = "xno" ; then - enable_log="0" -else - enable_log="1" -fi -], -[enable_log="0"] -) -if test "x$enable_log" = "x1" ; then - AC_DEFINE([JEMALLOC_LOG], [ ]) -fi -AC_SUBST([enable_log]) - -dnl Do not use readlinkat by default -AC_ARG_ENABLE([readlinkat], - [AS_HELP_STRING([--enable-readlinkat], [Use readlinkat over readlink])], -[if test "x$enable_readlinkat" = "xno" ; then - enable_readlinkat="0" -else - enable_readlinkat="1" -fi -], -[enable_readlinkat="0"] -) -if test "x$enable_readlinkat" = "x1" ; then - AC_DEFINE([JEMALLOC_READLINKAT], [ ]) -fi -AC_SUBST([enable_readlinkat]) - -dnl Avoid extra safety checks by default -AC_ARG_ENABLE([opt-safety-checks], - [AS_HELP_STRING([--enable-opt-safety-checks], - [Perform certain low-overhead checks, even in opt mode])], -[if test "x$enable_opt_safety_checks" = "xno" ; then - enable_opt_safety_checks="0" -else - enable_opt_safety_checks="1" -fi -], -[enable_opt_safety_checks="0"] -) -if test "x$enable_opt_safety_checks" = "x1" ; then - AC_DEFINE([JEMALLOC_OPT_SAFETY_CHECKS], [ ]) -fi -AC_SUBST([enable_opt_safety_checks]) - -JE_COMPILABLE([a program using __builtin_unreachable], [ -void foo (void) { - __builtin_unreachable(); -} -], [ - { - foo(); - } -], [je_cv_gcc_builtin_unreachable]) -if test "x${je_cv_gcc_builtin_unreachable}" = "xyes" ; then - AC_DEFINE([JEMALLOC_INTERNAL_UNREACHABLE], [__builtin_unreachable]) -else - AC_DEFINE([JEMALLOC_INTERNAL_UNREACHABLE], [abort]) -fi - -dnl ============================================================================ -dnl Check for __builtin_ffsl(), then ffsl(3), and fail if neither are found. -dnl One of those two functions should (theoretically) exist on all platforms -dnl that jemalloc currently has a chance of functioning on without modification. -dnl We additionally assume ffs[ll]() or __builtin_ffs[ll]() are defined if -dnl ffsl() or __builtin_ffsl() are defined, respectively. -JE_COMPILABLE([a program using __builtin_ffsl], [ -#include <stdio.h> -#include <strings.h> -#include <string.h> -], [ - { - int rv = __builtin_ffsl(0x08); - printf("%d\n", rv); - } -], [je_cv_gcc_builtin_ffsl]) -if test "x${je_cv_gcc_builtin_ffsl}" = "xyes" ; then - AC_DEFINE([JEMALLOC_INTERNAL_FFSLL], [__builtin_ffsll]) - AC_DEFINE([JEMALLOC_INTERNAL_FFSL], [__builtin_ffsl]) - AC_DEFINE([JEMALLOC_INTERNAL_FFS], [__builtin_ffs]) -else - JE_COMPILABLE([a program using ffsl], [ - #include <stdio.h> - #include <strings.h> - #include <string.h> - ], [ - { - int rv = ffsl(0x08); - printf("%d\n", rv); - } - ], [je_cv_function_ffsl]) - if test "x${je_cv_function_ffsl}" = "xyes" ; then - AC_DEFINE([JEMALLOC_INTERNAL_FFSLL], [ffsll]) - AC_DEFINE([JEMALLOC_INTERNAL_FFSL], [ffsl]) - AC_DEFINE([JEMALLOC_INTERNAL_FFS], [ffs]) - else - AC_MSG_ERROR([Cannot build without ffsl(3) or __builtin_ffsl()]) - fi -fi - -JE_COMPILABLE([a program using __builtin_popcountl], [ -#include <stdio.h> -#include <strings.h> -#include <string.h> -], [ - { - int rv = __builtin_popcountl(0x08); - printf("%d\n", rv); - } -], [je_cv_gcc_builtin_popcountl]) -if test "x${je_cv_gcc_builtin_popcountl}" = "xyes" ; then - AC_DEFINE([JEMALLOC_INTERNAL_POPCOUNT], [__builtin_popcount]) - AC_DEFINE([JEMALLOC_INTERNAL_POPCOUNTL], [__builtin_popcountl]) -fi - -AC_ARG_WITH([lg_quantum], - [AS_HELP_STRING([--with-lg-quantum=<lg-quantum>], - [Base 2 log of minimum allocation alignment])], - [LG_QUANTA="$with_lg_quantum"], - [LG_QUANTA="3 4"]) -if test "x$with_lg_quantum" != "x" ; then - AC_DEFINE_UNQUOTED([LG_QUANTUM], [$with_lg_quantum]) -fi - -AC_ARG_WITH([lg_page], - [AS_HELP_STRING([--with-lg-page=<lg-page>], [Base 2 log of system page size])], - [LG_PAGE="$with_lg_page"], [LG_PAGE="detect"]) -if test "x$LG_PAGE" = "xdetect"; then - AC_CACHE_CHECK([LG_PAGE], - [je_cv_lg_page], - AC_RUN_IFELSE([AC_LANG_PROGRAM( -[[ -#include <strings.h> -#ifdef _WIN32 -#include <windows.h> -#else -#include <unistd.h> -#endif -#include <stdio.h> -]], -[[ - int result; - FILE *f; - -#ifdef _WIN32 - SYSTEM_INFO si; - GetSystemInfo(&si); - result = si.dwPageSize; -#else - result = sysconf(_SC_PAGESIZE); -#endif - if (result == -1) { - return 1; - } - result = JEMALLOC_INTERNAL_FFSL(result) - 1; - - f = fopen("conftest.out", "w"); - if (f == NULL) { - return 1; - } - fprintf(f, "%d", result); - fclose(f); - - return 0; -]])], - [je_cv_lg_page=`cat conftest.out`], - [je_cv_lg_page=undefined], - [je_cv_lg_page=12])) -fi -if test "x${je_cv_lg_page}" != "x" ; then - LG_PAGE="${je_cv_lg_page}" -fi -if test "x${LG_PAGE}" != "xundefined" ; then - AC_DEFINE_UNQUOTED([LG_PAGE], [$LG_PAGE]) -else - AC_MSG_ERROR([cannot determine value for LG_PAGE]) -fi - -AC_ARG_WITH([lg_hugepage], - [AS_HELP_STRING([--with-lg-hugepage=<lg-hugepage>], - [Base 2 log of system huge page size])], - [je_cv_lg_hugepage="${with_lg_hugepage}"], - [je_cv_lg_hugepage=""]) -if test "x${je_cv_lg_hugepage}" = "x" ; then - dnl Look in /proc/meminfo (Linux-specific) for information on the default huge - dnl page size, if any. The relevant line looks like: - dnl - dnl Hugepagesize: 2048 kB - if test -e "/proc/meminfo" ; then - hpsk=[`cat /proc/meminfo 2>/dev/null | \ - grep -e '^Hugepagesize:[[:space:]]\+[0-9]\+[[:space:]]kB$' | \ - awk '{print $2}'`] - if test "x${hpsk}" != "x" ; then - je_cv_lg_hugepage=10 - while test "${hpsk}" -gt 1 ; do - hpsk="$((hpsk / 2))" - je_cv_lg_hugepage="$((je_cv_lg_hugepage + 1))" - done - fi - fi - - dnl Set default if unable to automatically configure. - if test "x${je_cv_lg_hugepage}" = "x" ; then - je_cv_lg_hugepage=21 - fi -fi -if test "x${LG_PAGE}" != "xundefined" -a \ - "${je_cv_lg_hugepage}" -lt "${LG_PAGE}" ; then - AC_MSG_ERROR([Huge page size (2^${je_cv_lg_hugepage}) must be at least page size (2^${LG_PAGE})]) -fi -AC_DEFINE_UNQUOTED([LG_HUGEPAGE], [${je_cv_lg_hugepage}]) - -dnl ============================================================================ -dnl Enable libdl by default. -AC_ARG_ENABLE([libdl], - [AS_HELP_STRING([--disable-libdl], - [Do not use libdl])], -[if test "x$enable_libdl" = "xno" ; then - enable_libdl="0" -else - enable_libdl="1" -fi -], -[enable_libdl="1"] -) -AC_SUBST([libdl]) - -dnl ============================================================================ -dnl Configure pthreads. - -if test "x$abi" != "xpecoff" ; then - AC_DEFINE([JEMALLOC_HAVE_PTHREAD], [ ]) - AC_CHECK_HEADERS([pthread.h], , [AC_MSG_ERROR([pthread.h is missing])]) - dnl Some systems may embed pthreads functionality in libc; check for libpthread - dnl first, but try libc too before failing. - AC_CHECK_LIB([pthread], [pthread_create], [JE_APPEND_VS(LIBS, -pthread)], - [AC_SEARCH_LIBS([pthread_create], , , - AC_MSG_ERROR([libpthread is missing]))]) - wrap_syms="${wrap_syms} pthread_create" - have_pthread="1" - -dnl Check if we have dlsym support. - if test "x$enable_libdl" = "x1" ; then - have_dlsym="1" - AC_CHECK_HEADERS([dlfcn.h], - AC_CHECK_FUNC([dlsym], [], - [AC_CHECK_LIB([dl], [dlsym], [LIBS="$LIBS -ldl"], [have_dlsym="0"])]), - [have_dlsym="0"]) - if test "x$have_dlsym" = "x1" ; then - AC_DEFINE([JEMALLOC_HAVE_DLSYM], [ ]) - fi - else - have_dlsym="0" - fi - - JE_COMPILABLE([pthread_atfork(3)], [ -#include <pthread.h> -], [ - pthread_atfork((void *)0, (void *)0, (void *)0); -], [je_cv_pthread_atfork]) - if test "x${je_cv_pthread_atfork}" = "xyes" ; then - AC_DEFINE([JEMALLOC_HAVE_PTHREAD_ATFORK], [ ]) - fi - dnl Check if pthread_setname_np is available with the expected API. - JE_COMPILABLE([pthread_setname_np(3)], [ -#include <pthread.h> -], [ - pthread_setname_np(pthread_self(), "setname_test"); -], [je_cv_pthread_setname_np]) - if test "x${je_cv_pthread_setname_np}" = "xyes" ; then - AC_DEFINE([JEMALLOC_HAVE_PTHREAD_SETNAME_NP], [ ]) - fi -fi - -JE_APPEND_VS(CPPFLAGS, -D_REENTRANT) - -dnl Check whether clock_gettime(2) is in libc or librt. -AC_SEARCH_LIBS([clock_gettime], [rt]) - -dnl Cray wrapper compiler often adds `-lrt` when using `-static`. Check with -dnl `-dynamic` as well in case a user tries to dynamically link in jemalloc -if test "x$je_cv_cray_prgenv_wrapper" = "xyes" ; then - if test "$ac_cv_search_clock_gettime" != "-lrt"; then - JE_CFLAGS_SAVE() - - unset ac_cv_search_clock_gettime - JE_CFLAGS_ADD([-dynamic]) - AC_SEARCH_LIBS([clock_gettime], [rt]) - - JE_CFLAGS_RESTORE() - fi -fi - -dnl check for CLOCK_MONOTONIC_COARSE (Linux-specific). -JE_COMPILABLE([clock_gettime(CLOCK_MONOTONIC_COARSE, ...)], [ -#include <time.h> -], [ - struct timespec ts; - - clock_gettime(CLOCK_MONOTONIC_COARSE, &ts); -], [je_cv_clock_monotonic_coarse]) -if test "x${je_cv_clock_monotonic_coarse}" = "xyes" ; then - AC_DEFINE([JEMALLOC_HAVE_CLOCK_MONOTONIC_COARSE]) -fi - -dnl check for CLOCK_MONOTONIC. -JE_COMPILABLE([clock_gettime(CLOCK_MONOTONIC, ...)], [ -#include <unistd.h> -#include <time.h> -], [ - struct timespec ts; - - clock_gettime(CLOCK_MONOTONIC, &ts); -#if !defined(_POSIX_MONOTONIC_CLOCK) || _POSIX_MONOTONIC_CLOCK < 0 -# error _POSIX_MONOTONIC_CLOCK missing/invalid -#endif -], [je_cv_clock_monotonic]) -if test "x${je_cv_clock_monotonic}" = "xyes" ; then - AC_DEFINE([JEMALLOC_HAVE_CLOCK_MONOTONIC]) -fi - -dnl Check for mach_absolute_time(). -JE_COMPILABLE([mach_absolute_time()], [ -#include <mach/mach_time.h> -], [ - mach_absolute_time(); -], [je_cv_mach_absolute_time]) -if test "x${je_cv_mach_absolute_time}" = "xyes" ; then - AC_DEFINE([JEMALLOC_HAVE_MACH_ABSOLUTE_TIME]) -fi - -dnl Use syscall(2) (if available) by default. -AC_ARG_ENABLE([syscall], - [AS_HELP_STRING([--disable-syscall], [Disable use of syscall(2)])], -[if test "x$enable_syscall" = "xno" ; then - enable_syscall="0" -else - enable_syscall="1" -fi -], -[enable_syscall="1"] -) -if test "x$enable_syscall" = "x1" ; then - dnl Check if syscall(2) is usable. Treat warnings as errors, so that e.g. OS - dnl X 10.12's deprecation warning prevents use. - JE_CFLAGS_SAVE() - JE_CFLAGS_ADD([-Werror]) - JE_COMPILABLE([syscall(2)], [ -#include <sys/syscall.h> -#include <unistd.h> -], [ - syscall(SYS_write, 2, "hello", 5); -], - [je_cv_syscall]) - JE_CFLAGS_RESTORE() - if test "x$je_cv_syscall" = "xyes" ; then - AC_DEFINE([JEMALLOC_USE_SYSCALL], [ ]) - fi -fi - -dnl Check if the GNU-specific secure_getenv function exists. -AC_CHECK_FUNC([secure_getenv], - [have_secure_getenv="1"], - [have_secure_getenv="0"] - ) -if test "x$have_secure_getenv" = "x1" ; then - AC_DEFINE([JEMALLOC_HAVE_SECURE_GETENV], [ ]) -fi - -dnl Check if the GNU-specific sched_getcpu function exists. -AC_CHECK_FUNC([sched_getcpu], - [have_sched_getcpu="1"], - [have_sched_getcpu="0"] - ) -if test "x$have_sched_getcpu" = "x1" ; then - AC_DEFINE([JEMALLOC_HAVE_SCHED_GETCPU], [ ]) -fi - -dnl Check if the GNU-specific sched_setaffinity function exists. -AC_CHECK_FUNC([sched_setaffinity], - [have_sched_setaffinity="1"], - [have_sched_setaffinity="0"] - ) -if test "x$have_sched_setaffinity" = "x1" ; then - AC_DEFINE([JEMALLOC_HAVE_SCHED_SETAFFINITY], [ ]) -fi - -dnl Check if the Solaris/BSD issetugid function exists. -AC_CHECK_FUNC([issetugid], - [have_issetugid="1"], - [have_issetugid="0"] - ) -if test "x$have_issetugid" = "x1" ; then - AC_DEFINE([JEMALLOC_HAVE_ISSETUGID], [ ]) -fi - -dnl Check whether the BSD-specific _malloc_thread_cleanup() exists. If so, use -dnl it rather than pthreads TSD cleanup functions to support cleanup during -dnl thread exit, in order to avoid pthreads library recursion during -dnl bootstrapping. -AC_CHECK_FUNC([_malloc_thread_cleanup], - [have__malloc_thread_cleanup="1"], - [have__malloc_thread_cleanup="0"] - ) -if test "x$have__malloc_thread_cleanup" = "x1" ; then - AC_DEFINE([JEMALLOC_MALLOC_THREAD_CLEANUP], [ ]) - wrap_syms="${wrap_syms} _malloc_thread_cleanup" - force_tls="1" -fi - -dnl Check whether the BSD-specific _pthread_mutex_init_calloc_cb() exists. If -dnl so, mutex initialization causes allocation, and we need to implement this -dnl callback function in order to prevent recursive allocation. -AC_CHECK_FUNC([_pthread_mutex_init_calloc_cb], - [have__pthread_mutex_init_calloc_cb="1"], - [have__pthread_mutex_init_calloc_cb="0"] - ) -if test "x$have__pthread_mutex_init_calloc_cb" = "x1" ; then - AC_DEFINE([JEMALLOC_MUTEX_INIT_CB]) - wrap_syms="${wrap_syms} _malloc_prefork _malloc_postfork" -fi - -dnl Disable lazy locking by default. -AC_ARG_ENABLE([lazy_lock], - [AS_HELP_STRING([--enable-lazy-lock], - [Enable lazy locking (only lock when multi-threaded)])], -[if test "x$enable_lazy_lock" = "xno" ; then - enable_lazy_lock="0" -else - enable_lazy_lock="1" -fi -], -[enable_lazy_lock=""] -) -if test "x${enable_lazy_lock}" = "x" ; then - if test "x${force_lazy_lock}" = "x1" ; then - AC_MSG_RESULT([Forcing lazy-lock to avoid allocator/threading bootstrap issues]) - enable_lazy_lock="1" - else - enable_lazy_lock="0" - fi -fi -if test "x${enable_lazy_lock}" = "x1" -a "x${abi}" = "xpecoff" ; then - AC_MSG_RESULT([Forcing no lazy-lock because thread creation monitoring is unimplemented]) - enable_lazy_lock="0" -fi -if test "x$enable_lazy_lock" = "x1" ; then - if test "x$have_dlsym" = "x1" ; then - AC_DEFINE([JEMALLOC_LAZY_LOCK], [ ]) - else - AC_MSG_ERROR([Missing dlsym support: lazy-lock cannot be enabled.]) - fi -fi -AC_SUBST([enable_lazy_lock]) - -dnl Automatically configure TLS. -if test "x${force_tls}" = "x1" ; then - enable_tls="1" -elif test "x${force_tls}" = "x0" ; then - enable_tls="0" -else - enable_tls="1" -fi -if test "x${enable_tls}" = "x1" ; then -AC_MSG_CHECKING([for TLS]) -AC_COMPILE_IFELSE([AC_LANG_PROGRAM( -[[ - __thread int x; -]], [[ - x = 42; - - return 0; -]])], - AC_MSG_RESULT([yes]), - AC_MSG_RESULT([no]) - enable_tls="0") -else - enable_tls="0" -fi -AC_SUBST([enable_tls]) -if test "x${enable_tls}" = "x1" ; then - AC_DEFINE_UNQUOTED([JEMALLOC_TLS], [ ]) -fi - -dnl ============================================================================ -dnl Check for C11 atomics. - -JE_COMPILABLE([C11 atomics], [ -#include <stdint.h> -#if (__STDC_VERSION__ >= 201112L) && !defined(__STDC_NO_ATOMICS__) -#include <stdatomic.h> -#else -#error Atomics not available -#endif -], [ - uint64_t *p = (uint64_t *)0; - uint64_t x = 1; - volatile atomic_uint_least64_t *a = (volatile atomic_uint_least64_t *)p; - uint64_t r = atomic_fetch_add(a, x) + x; - return r == 0; -], [je_cv_c11_atomics]) -if test "x${je_cv_c11_atomics}" = "xyes" ; then - AC_DEFINE([JEMALLOC_C11_ATOMICS]) -fi - -dnl ============================================================================ -dnl Check for GCC-style __atomic atomics. - -JE_COMPILABLE([GCC __atomic atomics], [ -], [ - int x = 0; - int val = 1; - int y = __atomic_fetch_add(&x, val, __ATOMIC_RELAXED); - int after_add = x; - return after_add == 1; -], [je_cv_gcc_atomic_atomics]) -if test "x${je_cv_gcc_atomic_atomics}" = "xyes" ; then - AC_DEFINE([JEMALLOC_GCC_ATOMIC_ATOMICS]) - - dnl check for 8-bit atomic support - JE_COMPILABLE([GCC 8-bit __atomic atomics], [ - ], [ - unsigned char x = 0; - int val = 1; - int y = __atomic_fetch_add(&x, val, __ATOMIC_RELAXED); - int after_add = (int)x; - return after_add == 1; - ], [je_cv_gcc_u8_atomic_atomics]) - if test "x${je_cv_gcc_u8_atomic_atomics}" = "xyes" ; then - AC_DEFINE([JEMALLOC_GCC_U8_ATOMIC_ATOMICS]) - fi -fi - -dnl ============================================================================ -dnl Check for GCC-style __sync atomics. - -JE_COMPILABLE([GCC __sync atomics], [ -], [ - int x = 0; - int before_add = __sync_fetch_and_add(&x, 1); - int after_add = x; - return (before_add == 0) && (after_add == 1); -], [je_cv_gcc_sync_atomics]) -if test "x${je_cv_gcc_sync_atomics}" = "xyes" ; then - AC_DEFINE([JEMALLOC_GCC_SYNC_ATOMICS]) - - dnl check for 8-bit atomic support - JE_COMPILABLE([GCC 8-bit __sync atomics], [ - ], [ - unsigned char x = 0; - int before_add = __sync_fetch_and_add(&x, 1); - int after_add = (int)x; - return (before_add == 0) && (after_add == 1); - ], [je_cv_gcc_u8_sync_atomics]) - if test "x${je_cv_gcc_u8_sync_atomics}" = "xyes" ; then - AC_DEFINE([JEMALLOC_GCC_U8_SYNC_ATOMICS]) - fi -fi - -dnl ============================================================================ -dnl Check for atomic(3) operations as provided on Darwin. -dnl We need this not for the atomic operations (which are provided above), but -dnl rather for the OS_unfair_lock type it exposes. - -JE_COMPILABLE([Darwin OSAtomic*()], [ -#include <libkern/OSAtomic.h> -#include <inttypes.h> -], [ - { - int32_t x32 = 0; - volatile int32_t *x32p = &x32; - OSAtomicAdd32(1, x32p); - } - { - int64_t x64 = 0; - volatile int64_t *x64p = &x64; - OSAtomicAdd64(1, x64p); - } -], [je_cv_osatomic]) -if test "x${je_cv_osatomic}" = "xyes" ; then - AC_DEFINE([JEMALLOC_OSATOMIC], [ ]) -fi - -dnl ============================================================================ -dnl Check for madvise(2). - -JE_COMPILABLE([madvise(2)], [ -#include <sys/mman.h> -], [ - madvise((void *)0, 0, 0); -], [je_cv_madvise]) -if test "x${je_cv_madvise}" = "xyes" ; then - AC_DEFINE([JEMALLOC_HAVE_MADVISE], [ ]) - - dnl Check for madvise(..., MADV_FREE). - JE_COMPILABLE([madvise(..., MADV_FREE)], [ -#include <sys/mman.h> -], [ - madvise((void *)0, 0, MADV_FREE); -], [je_cv_madv_free]) - if test "x${je_cv_madv_free}" = "xyes" ; then - AC_DEFINE([JEMALLOC_PURGE_MADVISE_FREE], [ ]) - elif test "x${je_cv_madvise}" = "xyes" ; then - case "${host_cpu}" in i686|x86_64) - case "${host}" in *-*-linux*) - AC_DEFINE([JEMALLOC_PURGE_MADVISE_FREE], [ ]) - AC_DEFINE([JEMALLOC_DEFINE_MADVISE_FREE], [ ]) - ;; - esac - ;; - esac - fi - - dnl Check for madvise(..., MADV_DONTNEED). - JE_COMPILABLE([madvise(..., MADV_DONTNEED)], [ -#include <sys/mman.h> -], [ - madvise((void *)0, 0, MADV_DONTNEED); -], [je_cv_madv_dontneed]) - if test "x${je_cv_madv_dontneed}" = "xyes" ; then - AC_DEFINE([JEMALLOC_PURGE_MADVISE_DONTNEED], [ ]) - fi - - dnl Check for madvise(..., MADV_DO[NT]DUMP). - JE_COMPILABLE([madvise(..., MADV_DO[[NT]]DUMP)], [ -#include <sys/mman.h> -], [ - madvise((void *)0, 0, MADV_DONTDUMP); - madvise((void *)0, 0, MADV_DODUMP); -], [je_cv_madv_dontdump]) - if test "x${je_cv_madv_dontdump}" = "xyes" ; then - AC_DEFINE([JEMALLOC_MADVISE_DONTDUMP], [ ]) - fi - - dnl Check for madvise(..., MADV_[NO]HUGEPAGE). - JE_COMPILABLE([madvise(..., MADV_[[NO]]HUGEPAGE)], [ -#include <sys/mman.h> -], [ - madvise((void *)0, 0, MADV_HUGEPAGE); - madvise((void *)0, 0, MADV_NOHUGEPAGE); -], [je_cv_thp]) -case "${host_cpu}" in - arm*) - ;; - *) - if test "x${je_cv_thp}" = "xyes" ; then - AC_DEFINE([JEMALLOC_HAVE_MADVISE_HUGE], [ ]) - fi - ;; -esac -fi - -dnl ============================================================================ -dnl Check for __builtin_clz() and __builtin_clzl(). - -AC_CACHE_CHECK([for __builtin_clz], - [je_cv_builtin_clz], - [AC_LINK_IFELSE([AC_LANG_PROGRAM([], - [ - { - unsigned x = 0; - int y = __builtin_clz(x); - } - { - unsigned long x = 0; - int y = __builtin_clzl(x); - } - ])], - [je_cv_builtin_clz=yes], - [je_cv_builtin_clz=no])]) - -if test "x${je_cv_builtin_clz}" = "xyes" ; then - AC_DEFINE([JEMALLOC_HAVE_BUILTIN_CLZ], [ ]) -fi - -dnl ============================================================================ -dnl Check for os_unfair_lock operations as provided on Darwin. - -JE_COMPILABLE([Darwin os_unfair_lock_*()], [ -#include <os/lock.h> -#include <AvailabilityMacros.h> -], [ - #if MAC_OS_X_VERSION_MIN_REQUIRED < 101200 - #error "os_unfair_lock is not supported" - #else - os_unfair_lock lock = OS_UNFAIR_LOCK_INIT; - os_unfair_lock_lock(&lock); - os_unfair_lock_unlock(&lock); - #endif -], [je_cv_os_unfair_lock]) -if test "x${je_cv_os_unfair_lock}" = "xyes" ; then - AC_DEFINE([JEMALLOC_OS_UNFAIR_LOCK], [ ]) -fi - -dnl ============================================================================ -dnl Darwin-related configuration. - -AC_ARG_ENABLE([zone-allocator], - [AS_HELP_STRING([--disable-zone-allocator], - [Disable zone allocator for Darwin])], -[if test "x$enable_zone_allocator" = "xno" ; then - enable_zone_allocator="0" -else - enable_zone_allocator="1" -fi -], -[if test "x${abi}" = "xmacho"; then - enable_zone_allocator="1" -fi -] -) -AC_SUBST([enable_zone_allocator]) - -if test "x${enable_zone_allocator}" = "x1" ; then - if test "x${abi}" != "xmacho"; then - AC_MSG_ERROR([--enable-zone-allocator is only supported on Darwin]) - fi - AC_DEFINE([JEMALLOC_ZONE], [ ]) -fi - -dnl ============================================================================ -dnl Use initial-exec TLS by default. -AC_ARG_ENABLE([initial-exec-tls], - [AS_HELP_STRING([--disable-initial-exec-tls], - [Disable the initial-exec tls model])], -[if test "x$enable_initial_exec_tls" = "xno" ; then - enable_initial_exec_tls="0" -else - enable_initial_exec_tls="1" -fi -], -[enable_initial_exec_tls="1"] -) -AC_SUBST([enable_initial_exec_tls]) - -if test "x${je_cv_tls_model}" = "xyes" -a \ - "x${enable_initial_exec_tls}" = "x1" ; then - AC_DEFINE([JEMALLOC_TLS_MODEL], - [__attribute__((tls_model("initial-exec")))]) -else - AC_DEFINE([JEMALLOC_TLS_MODEL], [ ]) -fi - -dnl ============================================================================ -dnl Enable background threads if possible. - -if test "x${have_pthread}" = "x1" -a "x${je_cv_os_unfair_lock}" != "xyes" ; then - AC_DEFINE([JEMALLOC_BACKGROUND_THREAD]) -fi - -dnl ============================================================================ -dnl Check for glibc malloc hooks - -JE_COMPILABLE([glibc malloc hook], [ -#include <stddef.h> - -extern void (* __free_hook)(void *ptr); -extern void *(* __malloc_hook)(size_t size); -extern void *(* __realloc_hook)(void *ptr, size_t size); -], [ - void *ptr = 0L; - if (__malloc_hook) ptr = __malloc_hook(1); - if (__realloc_hook) ptr = __realloc_hook(ptr, 2); - if (__free_hook && ptr) __free_hook(ptr); -], [je_cv_glibc_malloc_hook]) -if test "x${je_cv_glibc_malloc_hook}" = "xyes" ; then - if test "x${JEMALLOC_PREFIX}" = "x" ; then - AC_DEFINE([JEMALLOC_GLIBC_MALLOC_HOOK], [ ]) - wrap_syms="${wrap_syms} __free_hook __malloc_hook __realloc_hook" - fi -fi - -JE_COMPILABLE([glibc memalign hook], [ -#include <stddef.h> - -extern void *(* __memalign_hook)(size_t alignment, size_t size); -], [ - void *ptr = 0L; - if (__memalign_hook) ptr = __memalign_hook(16, 7); -], [je_cv_glibc_memalign_hook]) -if test "x${je_cv_glibc_memalign_hook}" = "xyes" ; then - if test "x${JEMALLOC_PREFIX}" = "x" ; then - AC_DEFINE([JEMALLOC_GLIBC_MEMALIGN_HOOK], [ ]) - wrap_syms="${wrap_syms} __memalign_hook" - fi -fi - -JE_COMPILABLE([pthreads adaptive mutexes], [ -#include <pthread.h> -], [ - pthread_mutexattr_t attr; - pthread_mutexattr_init(&attr); - pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ADAPTIVE_NP); - pthread_mutexattr_destroy(&attr); -], [je_cv_pthread_mutex_adaptive_np]) -if test "x${je_cv_pthread_mutex_adaptive_np}" = "xyes" ; then - AC_DEFINE([JEMALLOC_HAVE_PTHREAD_MUTEX_ADAPTIVE_NP], [ ]) -fi - -JE_CFLAGS_SAVE() -JE_CFLAGS_ADD([-D_GNU_SOURCE]) -JE_CFLAGS_ADD([-Werror]) -JE_CFLAGS_ADD([-herror_on_warning]) -JE_COMPILABLE([strerror_r returns char with gnu source], [ -#include <errno.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -], [ - char *buffer = (char *) malloc(100); - char *error = strerror_r(EINVAL, buffer, 100); - printf("%s\n", error); -], [je_cv_strerror_r_returns_char_with_gnu_source]) -JE_CFLAGS_RESTORE() -if test "x${je_cv_strerror_r_returns_char_with_gnu_source}" = "xyes" ; then - AC_DEFINE([JEMALLOC_STRERROR_R_RETURNS_CHAR_WITH_GNU_SOURCE], [ ]) -fi - -dnl ============================================================================ -dnl Check for typedefs, structures, and compiler characteristics. -AC_HEADER_STDBOOL - -dnl ============================================================================ -dnl Define commands that generate output files. - -AC_CONFIG_COMMANDS([include/jemalloc/internal/public_symbols.txt], [ - f="${objroot}include/jemalloc/internal/public_symbols.txt" - mkdir -p "${objroot}include/jemalloc/internal" - cp /dev/null "${f}" - for nm in `echo ${mangling_map} |tr ',' ' '` ; do - n=`echo ${nm} |tr ':' ' ' |awk '{print $[]1}'` - m=`echo ${nm} |tr ':' ' ' |awk '{print $[]2}'` - echo "${n}:${m}" >> "${f}" - dnl Remove name from public_syms so that it isn't redefined later. - public_syms=`for sym in ${public_syms}; do echo "${sym}"; done |grep -v "^${n}\$" |tr '\n' ' '` - done - for sym in ${public_syms} ; do - n="${sym}" - m="${JEMALLOC_PREFIX}${sym}" - echo "${n}:${m}" >> "${f}" - done -], [ - srcdir="${srcdir}" - objroot="${objroot}" - mangling_map="${mangling_map}" - public_syms="${public_syms}" - JEMALLOC_PREFIX="${JEMALLOC_PREFIX}" -]) -AC_CONFIG_COMMANDS([include/jemalloc/internal/private_symbols.awk], [ - f="${objroot}include/jemalloc/internal/private_symbols.awk" - mkdir -p "${objroot}include/jemalloc/internal" - export_syms=`for sym in ${public_syms}; do echo "${JEMALLOC_PREFIX}${sym}"; done; for sym in ${wrap_syms}; do echo "${sym}"; done;` - "${srcdir}/include/jemalloc/internal/private_symbols.sh" "${SYM_PREFIX}" ${export_syms} > "${objroot}include/jemalloc/internal/private_symbols.awk" -], [ - srcdir="${srcdir}" - objroot="${objroot}" - public_syms="${public_syms}" - wrap_syms="${wrap_syms}" - SYM_PREFIX="${SYM_PREFIX}" - JEMALLOC_PREFIX="${JEMALLOC_PREFIX}" -]) -AC_CONFIG_COMMANDS([include/jemalloc/internal/private_symbols_jet.awk], [ - f="${objroot}include/jemalloc/internal/private_symbols_jet.awk" - mkdir -p "${objroot}include/jemalloc/internal" - export_syms=`for sym in ${public_syms}; do echo "jet_${sym}"; done; for sym in ${wrap_syms}; do echo "${sym}"; done;` - "${srcdir}/include/jemalloc/internal/private_symbols.sh" "${SYM_PREFIX}" ${export_syms} > "${objroot}include/jemalloc/internal/private_symbols_jet.awk" -], [ - srcdir="${srcdir}" - objroot="${objroot}" - public_syms="${public_syms}" - wrap_syms="${wrap_syms}" - SYM_PREFIX="${SYM_PREFIX}" -]) -AC_CONFIG_COMMANDS([include/jemalloc/internal/public_namespace.h], [ - mkdir -p "${objroot}include/jemalloc/internal" - "${srcdir}/include/jemalloc/internal/public_namespace.sh" "${objroot}include/jemalloc/internal/public_symbols.txt" > "${objroot}include/jemalloc/internal/public_namespace.h" -], [ - srcdir="${srcdir}" - objroot="${objroot}" -]) -AC_CONFIG_COMMANDS([include/jemalloc/internal/public_unnamespace.h], [ - mkdir -p "${objroot}include/jemalloc/internal" - "${srcdir}/include/jemalloc/internal/public_unnamespace.sh" "${objroot}include/jemalloc/internal/public_symbols.txt" > "${objroot}include/jemalloc/internal/public_unnamespace.h" -], [ - srcdir="${srcdir}" - objroot="${objroot}" -]) -AC_CONFIG_COMMANDS([include/jemalloc/jemalloc_protos_jet.h], [ - mkdir -p "${objroot}include/jemalloc" - cat "${srcdir}/include/jemalloc/jemalloc_protos.h.in" | sed -e 's/@je_@/jet_/g' > "${objroot}include/jemalloc/jemalloc_protos_jet.h" -], [ - srcdir="${srcdir}" - objroot="${objroot}" -]) -AC_CONFIG_COMMANDS([include/jemalloc/jemalloc_rename.h], [ - mkdir -p "${objroot}include/jemalloc" - "${srcdir}/include/jemalloc/jemalloc_rename.sh" "${objroot}include/jemalloc/internal/public_symbols.txt" > "${objroot}include/jemalloc/jemalloc_rename.h" -], [ - srcdir="${srcdir}" - objroot="${objroot}" -]) -AC_CONFIG_COMMANDS([include/jemalloc/jemalloc_mangle.h], [ - mkdir -p "${objroot}include/jemalloc" - "${srcdir}/include/jemalloc/jemalloc_mangle.sh" "${objroot}include/jemalloc/internal/public_symbols.txt" je_ > "${objroot}include/jemalloc/jemalloc_mangle.h" -], [ - srcdir="${srcdir}" - objroot="${objroot}" -]) -AC_CONFIG_COMMANDS([include/jemalloc/jemalloc_mangle_jet.h], [ - mkdir -p "${objroot}include/jemalloc" - "${srcdir}/include/jemalloc/jemalloc_mangle.sh" "${objroot}include/jemalloc/internal/public_symbols.txt" jet_ > "${objroot}include/jemalloc/jemalloc_mangle_jet.h" -], [ - srcdir="${srcdir}" - objroot="${objroot}" -]) -AC_CONFIG_COMMANDS([include/jemalloc/jemalloc.h], [ - mkdir -p "${objroot}include/jemalloc" - "${srcdir}/include/jemalloc/jemalloc.sh" "${objroot}" > "${objroot}include/jemalloc/jemalloc${install_suffix}.h" -], [ - srcdir="${srcdir}" - objroot="${objroot}" - install_suffix="${install_suffix}" -]) - -dnl Process .in files. -AC_SUBST([cfghdrs_in]) -AC_SUBST([cfghdrs_out]) -AC_CONFIG_HEADERS([$cfghdrs_tup]) - -dnl ============================================================================ -dnl Generate outputs. - -AC_CONFIG_FILES([$cfgoutputs_tup config.stamp bin/jemalloc-config bin/jemalloc.sh bin/jeprof]) -AC_SUBST([cfgoutputs_in]) -AC_SUBST([cfgoutputs_out]) -AC_OUTPUT - -dnl ============================================================================ -dnl Print out the results of configuration. -AC_MSG_RESULT([===============================================================================]) -AC_MSG_RESULT([jemalloc version : ${jemalloc_version}]) -AC_MSG_RESULT([library revision : ${rev}]) -AC_MSG_RESULT([]) -AC_MSG_RESULT([CONFIG : ${CONFIG}]) -AC_MSG_RESULT([CC : ${CC}]) -AC_MSG_RESULT([CONFIGURE_CFLAGS : ${CONFIGURE_CFLAGS}]) -AC_MSG_RESULT([SPECIFIED_CFLAGS : ${SPECIFIED_CFLAGS}]) -AC_MSG_RESULT([EXTRA_CFLAGS : ${EXTRA_CFLAGS}]) -AC_MSG_RESULT([CPPFLAGS : ${CPPFLAGS}]) -AC_MSG_RESULT([CXX : ${CXX}]) -AC_MSG_RESULT([CONFIGURE_CXXFLAGS : ${CONFIGURE_CXXFLAGS}]) -AC_MSG_RESULT([SPECIFIED_CXXFLAGS : ${SPECIFIED_CXXFLAGS}]) -AC_MSG_RESULT([EXTRA_CXXFLAGS : ${EXTRA_CXXFLAGS}]) -AC_MSG_RESULT([LDFLAGS : ${LDFLAGS}]) -AC_MSG_RESULT([EXTRA_LDFLAGS : ${EXTRA_LDFLAGS}]) -AC_MSG_RESULT([DSO_LDFLAGS : ${DSO_LDFLAGS}]) -AC_MSG_RESULT([LIBS : ${LIBS}]) -AC_MSG_RESULT([RPATH_EXTRA : ${RPATH_EXTRA}]) -AC_MSG_RESULT([]) -AC_MSG_RESULT([XSLTPROC : ${XSLTPROC}]) -AC_MSG_RESULT([XSLROOT : ${XSLROOT}]) -AC_MSG_RESULT([]) -AC_MSG_RESULT([PREFIX : ${PREFIX}]) -AC_MSG_RESULT([BINDIR : ${BINDIR}]) -AC_MSG_RESULT([DATADIR : ${DATADIR}]) -AC_MSG_RESULT([INCLUDEDIR : ${INCLUDEDIR}]) -AC_MSG_RESULT([LIBDIR : ${LIBDIR}]) -AC_MSG_RESULT([MANDIR : ${MANDIR}]) -AC_MSG_RESULT([]) -AC_MSG_RESULT([srcroot : ${srcroot}]) -AC_MSG_RESULT([abs_srcroot : ${abs_srcroot}]) -AC_MSG_RESULT([objroot : ${objroot}]) -AC_MSG_RESULT([abs_objroot : ${abs_objroot}]) -AC_MSG_RESULT([]) -AC_MSG_RESULT([JEMALLOC_PREFIX : ${JEMALLOC_PREFIX}]) -AC_MSG_RESULT([JEMALLOC_PRIVATE_NAMESPACE]) -AC_MSG_RESULT([ : ${JEMALLOC_PRIVATE_NAMESPACE}]) -AC_MSG_RESULT([install_suffix : ${install_suffix}]) -AC_MSG_RESULT([malloc_conf : ${config_malloc_conf}]) -AC_MSG_RESULT([documentation : ${enable_doc}]) -AC_MSG_RESULT([shared libs : ${enable_shared}]) -AC_MSG_RESULT([static libs : ${enable_static}]) -AC_MSG_RESULT([autogen : ${enable_autogen}]) -AC_MSG_RESULT([debug : ${enable_debug}]) -AC_MSG_RESULT([stats : ${enable_stats}]) -AC_MSG_RESULT([experimetal_smallocx : ${enable_experimental_smallocx}]) -AC_MSG_RESULT([prof : ${enable_prof}]) -AC_MSG_RESULT([prof-libunwind : ${enable_prof_libunwind}]) -AC_MSG_RESULT([prof-libgcc : ${enable_prof_libgcc}]) -AC_MSG_RESULT([prof-gcc : ${enable_prof_gcc}]) -AC_MSG_RESULT([fill : ${enable_fill}]) -AC_MSG_RESULT([utrace : ${enable_utrace}]) -AC_MSG_RESULT([xmalloc : ${enable_xmalloc}]) -AC_MSG_RESULT([log : ${enable_log}]) -AC_MSG_RESULT([lazy_lock : ${enable_lazy_lock}]) -AC_MSG_RESULT([cache-oblivious : ${enable_cache_oblivious}]) -AC_MSG_RESULT([cxx : ${enable_cxx}]) -AC_MSG_RESULT([===============================================================================]) ->>>>>>> main diff --git a/contrib/jemalloc/doc/jemalloc.xml.in b/contrib/jemalloc/doc/jemalloc.xml.in index e2b15de21961..4f5d27996816 100644 --- a/contrib/jemalloc/doc/jemalloc.xml.in +++ b/contrib/jemalloc/doc/jemalloc.xml.in @@ -1,4 +1,3 @@ -<<<<<<< HEAD <?xml version='1.0' encoding='UTF-8'?> <?xml-stylesheet type="text/xsl" href="http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl"?> @@ -3787,3544 +3786,3 @@ malloc_conf = "narenas:1";]]></programlisting></para> 11.0.</para> </refsect1> </refentry> -||||||| dec341af7695 -======= -<?xml version='1.0' encoding='UTF-8'?> -<?xml-stylesheet type="text/xsl" - href="http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl"?> -<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" - "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [ -]> - -<refentry> - <refentryinfo> - <title>User Manual</title> - <productname>jemalloc</productname> - <releaseinfo role="version">@jemalloc_version@</releaseinfo> - <authorgroup> - <author> - <firstname>Jason</firstname> - <surname>Evans</surname> - <personblurb>Author</personblurb> - </author> - </authorgroup> - </refentryinfo> - <refmeta> - <refentrytitle>JEMALLOC</refentrytitle> - <manvolnum>3</manvolnum> - </refmeta> - <refnamediv> - <refdescriptor>jemalloc</refdescriptor> - <refname>jemalloc</refname> - <!-- Each refname causes a man page file to be created. Only if this were - the system malloc(3) implementation would these files be appropriate. - <refname>malloc</refname> - <refname>calloc</refname> - <refname>posix_memalign</refname> - <refname>aligned_alloc</refname> - <refname>realloc</refname> - <refname>free</refname> - <refname>mallocx</refname> - <refname>rallocx</refname> - <refname>xallocx</refname> - <refname>sallocx</refname> - <refname>dallocx</refname> - <refname>sdallocx</refname> - <refname>nallocx</refname> - <refname>mallctl</refname> - <refname>mallctlnametomib</refname> - <refname>mallctlbymib</refname> - <refname>malloc_stats_print</refname> - <refname>malloc_usable_size</refname> - --> - <refpurpose>general purpose memory allocation functions</refpurpose> - </refnamediv> - <refsect1 id="library"> - <title>LIBRARY</title> - <para>This manual describes jemalloc @jemalloc_version@. More information - can be found at the <ulink - url="http://jemalloc.net/">jemalloc website</ulink>.</para> - - <para>The following configuration options are enabled in libc's built-in - jemalloc: <option>--enable-fill</option>, - <option>--enable-lazy-lock</option>, <option>--enable-stats</option>, - <option>--enable-utrace</option>, <option>--enable-xmalloc</option>, and - <option>--with-malloc-conf=abort_conf:false</option>. - Additionally, <option>--enable-debug</option> is enabled in development - versions of FreeBSD (controlled by the - <constant>MK_MALLOC_PRODUCTION</constant> make variable).</para> - - </refsect1> - <refsynopsisdiv> - <title>SYNOPSIS</title> - <funcsynopsis> - <funcsynopsisinfo>#include <<filename class="headerfile">stdlib.h</filename>> -#include <<filename class="headerfile">malloc_np.h</filename>></funcsynopsisinfo> - <refsect2> - <title>Standard API</title> - <funcprototype> - <funcdef>void *<function>malloc</function></funcdef> - <paramdef>size_t <parameter>size</parameter></paramdef> - </funcprototype> - <funcprototype> - <funcdef>void *<function>calloc</function></funcdef> - <paramdef>size_t <parameter>number</parameter></paramdef> - <paramdef>size_t <parameter>size</parameter></paramdef> - </funcprototype> - <funcprototype> - <funcdef>int <function>posix_memalign</function></funcdef> - <paramdef>void **<parameter>ptr</parameter></paramdef> - <paramdef>size_t <parameter>alignment</parameter></paramdef> - <paramdef>size_t <parameter>size</parameter></paramdef> - </funcprototype> - <funcprototype> - <funcdef>void *<function>aligned_alloc</function></funcdef> - <paramdef>size_t <parameter>alignment</parameter></paramdef> - <paramdef>size_t <parameter>size</parameter></paramdef> - </funcprototype> - <funcprototype> - <funcdef>void *<function>realloc</function></funcdef> - <paramdef>void *<parameter>ptr</parameter></paramdef> - <paramdef>size_t <parameter>size</parameter></paramdef> - </funcprototype> - <funcprototype> - <funcdef>void <function>free</function></funcdef> - <paramdef>void *<parameter>ptr</parameter></paramdef> - </funcprototype> - </refsect2> - <refsect2> - <title>Non-standard API</title> - <funcprototype> - <funcdef>void *<function>mallocx</function></funcdef> - <paramdef>size_t <parameter>size</parameter></paramdef> - <paramdef>int <parameter>flags</parameter></paramdef> - </funcprototype> - <funcprototype> - <funcdef>void *<function>rallocx</function></funcdef> - <paramdef>void *<parameter>ptr</parameter></paramdef> - <paramdef>size_t <parameter>size</parameter></paramdef> - <paramdef>int <parameter>flags</parameter></paramdef> - </funcprototype> - <funcprototype> - <funcdef>size_t <function>xallocx</function></funcdef> - <paramdef>void *<parameter>ptr</parameter></paramdef> - <paramdef>size_t <parameter>size</parameter></paramdef> - <paramdef>size_t <parameter>extra</parameter></paramdef> - <paramdef>int <parameter>flags</parameter></paramdef> - </funcprototype> - <funcprototype> - <funcdef>size_t <function>sallocx</function></funcdef> - <paramdef>void *<parameter>ptr</parameter></paramdef> - <paramdef>int <parameter>flags</parameter></paramdef> - </funcprototype> - <funcprototype> - <funcdef>void <function>dallocx</function></funcdef> - <paramdef>void *<parameter>ptr</parameter></paramdef> - <paramdef>int <parameter>flags</parameter></paramdef> - </funcprototype> - <funcprototype> - <funcdef>void <function>sdallocx</function></funcdef> - <paramdef>void *<parameter>ptr</parameter></paramdef> - <paramdef>size_t <parameter>size</parameter></paramdef> - <paramdef>int <parameter>flags</parameter></paramdef> - </funcprototype> - <funcprototype> - <funcdef>size_t <function>nallocx</function></funcdef> - <paramdef>size_t <parameter>size</parameter></paramdef> - <paramdef>int <parameter>flags</parameter></paramdef> - </funcprototype> - <funcprototype> - <funcdef>int <function>mallctl</function></funcdef> - <paramdef>const char *<parameter>name</parameter></paramdef> - <paramdef>void *<parameter>oldp</parameter></paramdef> - <paramdef>size_t *<parameter>oldlenp</parameter></paramdef> - <paramdef>void *<parameter>newp</parameter></paramdef> - <paramdef>size_t <parameter>newlen</parameter></paramdef> - </funcprototype> - <funcprototype> - <funcdef>int <function>mallctlnametomib</function></funcdef> - <paramdef>const char *<parameter>name</parameter></paramdef> - <paramdef>size_t *<parameter>mibp</parameter></paramdef> - <paramdef>size_t *<parameter>miblenp</parameter></paramdef> - </funcprototype> - <funcprototype> - <funcdef>int <function>mallctlbymib</function></funcdef> - <paramdef>const size_t *<parameter>mib</parameter></paramdef> - <paramdef>size_t <parameter>miblen</parameter></paramdef> - <paramdef>void *<parameter>oldp</parameter></paramdef> - <paramdef>size_t *<parameter>oldlenp</parameter></paramdef> - <paramdef>void *<parameter>newp</parameter></paramdef> - <paramdef>size_t <parameter>newlen</parameter></paramdef> - </funcprototype> - <funcprototype> - <funcdef>void <function>malloc_stats_print</function></funcdef> - <paramdef>void <parameter>(*write_cb)</parameter> - <funcparams>void *, const char *</funcparams> - </paramdef> - <paramdef>void *<parameter>cbopaque</parameter></paramdef> - <paramdef>const char *<parameter>opts</parameter></paramdef> - </funcprototype> - <funcprototype> - <funcdef>size_t <function>malloc_usable_size</function></funcdef> - <paramdef>const void *<parameter>ptr</parameter></paramdef> - </funcprototype> - <funcprototype> - <funcdef>void <function>(*malloc_message)</function></funcdef> - <paramdef>void *<parameter>cbopaque</parameter></paramdef> - <paramdef>const char *<parameter>s</parameter></paramdef> - </funcprototype> - <para><type>const char *</type><varname>malloc_conf</varname>;</para> - </refsect2> - </funcsynopsis> - </refsynopsisdiv> - <refsect1 id="description"> - <title>DESCRIPTION</title> - <refsect2> - <title>Standard API</title> - - <para>The <function>malloc()</function> function allocates - <parameter>size</parameter> bytes of uninitialized memory. The allocated - space is suitably aligned (after possible pointer coercion) for storage - of any type of object.</para> - - <para>The <function>calloc()</function> function allocates - space for <parameter>number</parameter> objects, each - <parameter>size</parameter> bytes in length. The result is identical to - calling <function>malloc()</function> with an argument of - <parameter>number</parameter> * <parameter>size</parameter>, with the - exception that the allocated memory is explicitly initialized to zero - bytes.</para> - - <para>The <function>posix_memalign()</function> function - allocates <parameter>size</parameter> bytes of memory such that the - allocation's base address is a multiple of - <parameter>alignment</parameter>, and returns the allocation in the value - pointed to by <parameter>ptr</parameter>. The requested - <parameter>alignment</parameter> must be a power of 2 at least as large as - <code language="C">sizeof(<type>void *</type>)</code>.</para> - - <para>The <function>aligned_alloc()</function> function - allocates <parameter>size</parameter> bytes of memory such that the - allocation's base address is a multiple of - <parameter>alignment</parameter>. The requested - <parameter>alignment</parameter> must be a power of 2. Behavior is - undefined if <parameter>size</parameter> is not an integral multiple of - <parameter>alignment</parameter>.</para> - - <para>The <function>realloc()</function> function changes the - size of the previously allocated memory referenced by - <parameter>ptr</parameter> to <parameter>size</parameter> bytes. The - contents of the memory are unchanged up to the lesser of the new and old - sizes. If the new size is larger, the contents of the newly allocated - portion of the memory are undefined. Upon success, the memory referenced - by <parameter>ptr</parameter> is freed and a pointer to the newly - allocated memory is returned. Note that - <function>realloc()</function> may move the memory allocation, - resulting in a different return value than <parameter>ptr</parameter>. - If <parameter>ptr</parameter> is <constant>NULL</constant>, the - <function>realloc()</function> function behaves identically to - <function>malloc()</function> for the specified size.</para> - - <para>The <function>free()</function> function causes the - allocated memory referenced by <parameter>ptr</parameter> to be made - available for future allocations. If <parameter>ptr</parameter> is - <constant>NULL</constant>, no action occurs.</para> - </refsect2> - <refsect2> - <title>Non-standard API</title> - <para>The <function>mallocx()</function>, - <function>rallocx()</function>, - <function>xallocx()</function>, - <function>sallocx()</function>, - <function>dallocx()</function>, - <function>sdallocx()</function>, and - <function>nallocx()</function> functions all have a - <parameter>flags</parameter> argument that can be used to specify - options. The functions only check the options that are contextually - relevant. Use bitwise or (<code language="C">|</code>) operations to - specify one or more of the following: - <variablelist> - <varlistentry id="MALLOCX_LG_ALIGN"> - <term><constant>MALLOCX_LG_ALIGN(<parameter>la</parameter>) - </constant></term> - - <listitem><para>Align the memory allocation to start at an address - that is a multiple of <code language="C">(1 << - <parameter>la</parameter>)</code>. This macro does not validate - that <parameter>la</parameter> is within the valid - range.</para></listitem> - </varlistentry> - <varlistentry id="MALLOCX_ALIGN"> - <term><constant>MALLOCX_ALIGN(<parameter>a</parameter>) - </constant></term> - - <listitem><para>Align the memory allocation to start at an address - that is a multiple of <parameter>a</parameter>, where - <parameter>a</parameter> is a power of two. This macro does not - validate that <parameter>a</parameter> is a power of 2. - </para></listitem> - </varlistentry> - <varlistentry id="MALLOCX_ZERO"> - <term><constant>MALLOCX_ZERO</constant></term> - - <listitem><para>Initialize newly allocated memory to contain zero - bytes. In the growing reallocation case, the real size prior to - reallocation defines the boundary between untouched bytes and those - that are initialized to contain zero bytes. If this macro is - absent, newly allocated memory is uninitialized.</para></listitem> - </varlistentry> - <varlistentry id="MALLOCX_TCACHE"> - <term><constant>MALLOCX_TCACHE(<parameter>tc</parameter>) - </constant></term> - - <listitem><para>Use the thread-specific cache (tcache) specified by - the identifier <parameter>tc</parameter>, which must have been - acquired via the <link - linkend="tcache.create"><mallctl>tcache.create</mallctl></link> - mallctl. This macro does not validate that - <parameter>tc</parameter> specifies a valid - identifier.</para></listitem> - </varlistentry> - <varlistentry id="MALLOC_TCACHE_NONE"> - <term><constant>MALLOCX_TCACHE_NONE</constant></term> - - <listitem><para>Do not use a thread-specific cache (tcache). Unless - <constant>MALLOCX_TCACHE(<parameter>tc</parameter>)</constant> or - <constant>MALLOCX_TCACHE_NONE</constant> is specified, an - automatically managed tcache will be used under many circumstances. - This macro cannot be used in the same <parameter>flags</parameter> - argument as - <constant>MALLOCX_TCACHE(<parameter>tc</parameter>)</constant>.</para></listitem> - </varlistentry> - <varlistentry id="MALLOCX_ARENA"> - <term><constant>MALLOCX_ARENA(<parameter>a</parameter>) - </constant></term> - - <listitem><para>Use the arena specified by the index - <parameter>a</parameter>. This macro has no effect for regions that - were allocated via an arena other than the one specified. This - macro does not validate that <parameter>a</parameter> specifies an - arena index in the valid range.</para></listitem> - </varlistentry> - </variablelist> - </para> - - <para>The <function>mallocx()</function> function allocates at - least <parameter>size</parameter> bytes of memory, and returns a pointer - to the base address of the allocation. Behavior is undefined if - <parameter>size</parameter> is <constant>0</constant>.</para> - - <para>The <function>rallocx()</function> function resizes the - allocation at <parameter>ptr</parameter> to be at least - <parameter>size</parameter> bytes, and returns a pointer to the base - address of the resulting allocation, which may or may not have moved from - its original location. Behavior is undefined if - <parameter>size</parameter> is <constant>0</constant>.</para> - - <para>The <function>xallocx()</function> function resizes the - allocation at <parameter>ptr</parameter> in place to be at least - <parameter>size</parameter> bytes, and returns the real size of the - allocation. If <parameter>extra</parameter> is non-zero, an attempt is - made to resize the allocation to be at least <code - language="C">(<parameter>size</parameter> + - <parameter>extra</parameter>)</code> bytes, though inability to allocate - the extra byte(s) will not by itself result in failure to resize. - Behavior is undefined if <parameter>size</parameter> is - <constant>0</constant>, or if <code - language="C">(<parameter>size</parameter> + <parameter>extra</parameter> - > <constant>SIZE_T_MAX</constant>)</code>.</para> - - <para>The <function>sallocx()</function> function returns the - real size of the allocation at <parameter>ptr</parameter>.</para> - - <para>The <function>dallocx()</function> function causes the - memory referenced by <parameter>ptr</parameter> to be made available for - future allocations.</para> - - <para>The <function>sdallocx()</function> function is an - extension of <function>dallocx()</function> with a - <parameter>size</parameter> parameter to allow the caller to pass in the - allocation size as an optimization. The minimum valid input size is the - original requested size of the allocation, and the maximum valid input - size is the corresponding value returned by - <function>nallocx()</function> or - <function>sallocx()</function>.</para> - - <para>The <function>nallocx()</function> function allocates no - memory, but it performs the same size computation as the - <function>mallocx()</function> function, and returns the real - size of the allocation that would result from the equivalent - <function>mallocx()</function> function call, or - <constant>0</constant> if the inputs exceed the maximum supported size - class and/or alignment. Behavior is undefined if - <parameter>size</parameter> is <constant>0</constant>.</para> - - <para>The <function>mallctl()</function> function provides a - general interface for introspecting the memory allocator, as well as - setting modifiable parameters and triggering actions. The - period-separated <parameter>name</parameter> argument specifies a - location in a tree-structured namespace; see the <xref - linkend="mallctl_namespace" xrefstyle="template:%t"/> section for - documentation on the tree contents. To read a value, pass a pointer via - <parameter>oldp</parameter> to adequate space to contain the value, and a - pointer to its length via <parameter>oldlenp</parameter>; otherwise pass - <constant>NULL</constant> and <constant>NULL</constant>. Similarly, to - write a value, pass a pointer to the value via - <parameter>newp</parameter>, and its length via - <parameter>newlen</parameter>; otherwise pass <constant>NULL</constant> - and <constant>0</constant>.</para> - - <para>The <function>mallctlnametomib()</function> function - provides a way to avoid repeated name lookups for applications that - repeatedly query the same portion of the namespace, by translating a name - to a <quote>Management Information Base</quote> (MIB) that can be passed - repeatedly to <function>mallctlbymib()</function>. Upon - successful return from <function>mallctlnametomib()</function>, - <parameter>mibp</parameter> contains an array of - <parameter>*miblenp</parameter> integers, where - <parameter>*miblenp</parameter> is the lesser of the number of components - in <parameter>name</parameter> and the input value of - <parameter>*miblenp</parameter>. Thus it is possible to pass a - <parameter>*miblenp</parameter> that is smaller than the number of - period-separated name components, which results in a partial MIB that can - be used as the basis for constructing a complete MIB. For name - components that are integers (e.g. the 2 in - <link - linkend="arenas.bin.i.size"><mallctl>arenas.bin.2.size</mallctl></link>), - the corresponding MIB component will always be that integer. Therefore, - it is legitimate to construct code like the following: <programlisting - language="C"><![CDATA[ -unsigned nbins, i; -size_t mib[4]; -size_t len, miblen; - -len = sizeof(nbins); -mallctl("arenas.nbins", &nbins, &len, NULL, 0); - -miblen = 4; -mallctlnametomib("arenas.bin.0.size", mib, &miblen); -for (i = 0; i < nbins; i++) { - size_t bin_size; - - mib[2] = i; - len = sizeof(bin_size); - mallctlbymib(mib, miblen, (void *)&bin_size, &len, NULL, 0); - /* Do something with bin_size... */ -}]]></programlisting></para> - - <varlistentry id="malloc_stats_print_opts"> - </varlistentry> - <para>The <function>malloc_stats_print()</function> function writes - summary statistics via the <parameter>write_cb</parameter> callback - function pointer and <parameter>cbopaque</parameter> data passed to - <parameter>write_cb</parameter>, or <function>malloc_message()</function> - if <parameter>write_cb</parameter> is <constant>NULL</constant>. The - statistics are presented in human-readable form unless <quote>J</quote> is - specified as a character within the <parameter>opts</parameter> string, in - which case the statistics are presented in <ulink - url="http://www.json.org/">JSON format</ulink>. This function can be - called repeatedly. General information that never changes during - execution can be omitted by specifying <quote>g</quote> as a character - within the <parameter>opts</parameter> string. Note that - <function>malloc_stats_print()</function> uses the - <function>mallctl*()</function> functions internally, so inconsistent - statistics can be reported if multiple threads use these functions - simultaneously. If <option>--enable-stats</option> is specified during - configuration, <quote>m</quote>, <quote>d</quote>, and <quote>a</quote> - can be specified to omit merged arena, destroyed merged arena, and per - arena statistics, respectively; <quote>b</quote> and <quote>l</quote> can - be specified to omit per size class statistics for bins and large objects, - respectively; <quote>x</quote> can be specified to omit all mutex - statistics; <quote>e</quote> can be used to omit extent statistics. - Unrecognized characters are silently ignored. Note that thread caching - may prevent some statistics from being completely up to date, since extra - locking would be required to merge counters that track thread cache - operations.</para> - - <para>The <function>malloc_usable_size()</function> function - returns the usable size of the allocation pointed to by - <parameter>ptr</parameter>. The return value may be larger than the size - that was requested during allocation. The - <function>malloc_usable_size()</function> function is not a - mechanism for in-place <function>realloc()</function>; rather - it is provided solely as a tool for introspection purposes. Any - discrepancy between the requested allocation size and the size reported - by <function>malloc_usable_size()</function> should not be - depended on, since such behavior is entirely implementation-dependent. - </para> - </refsect2> - </refsect1> - <refsect1 id="tuning"> - <title>TUNING</title> - <para>Once, when the first call is made to one of the memory allocation - routines, the allocator initializes its internals based in part on various - options that can be specified at compile- or run-time.</para> - - <para>The string specified via <option>--with-malloc-conf</option>, the - string pointed to by the global variable <varname>malloc_conf</varname>, the - <quote>name</quote> of the file referenced by the symbolic link named - <filename class="symlink">/etc/malloc.conf</filename>, and the value of the - environment variable <envar>MALLOC_CONF</envar>, will be interpreted, in - that order, from left to right as options. Note that - <varname>malloc_conf</varname> may be read before - <function>main()</function> is entered, so the declaration of - <varname>malloc_conf</varname> should specify an initializer that contains - the final value to be read by jemalloc. <option>--with-malloc-conf</option> - and <varname>malloc_conf</varname> are compile-time mechanisms, whereas - <filename class="symlink">/etc/malloc.conf</filename> and - <envar>MALLOC_CONF</envar> can be safely set any time prior to program - invocation.</para> - - <para>An options string is a comma-separated list of option:value pairs. - There is one key corresponding to each <link - linkend="opt.abort"><mallctl>opt.*</mallctl></link> mallctl (see the <xref - linkend="mallctl_namespace" xrefstyle="template:%t"/> section for options - documentation). For example, <literal>abort:true,narenas:1</literal> sets - the <link linkend="opt.abort"><mallctl>opt.abort</mallctl></link> and <link - linkend="opt.narenas"><mallctl>opt.narenas</mallctl></link> options. Some - options have boolean values (true/false), others have integer values (base - 8, 10, or 16, depending on prefix), and yet others have raw string - values.</para> - </refsect1> - <refsect1 id="implementation_notes"> - <title>IMPLEMENTATION NOTES</title> - <para>Traditionally, allocators have used - <citerefentry><refentrytitle>sbrk</refentrytitle> - <manvolnum>2</manvolnum></citerefentry> to obtain memory, which is - suboptimal for several reasons, including race conditions, increased - fragmentation, and artificial limitations on maximum usable memory. If - <citerefentry><refentrytitle>sbrk</refentrytitle> - <manvolnum>2</manvolnum></citerefentry> is supported by the operating - system, this allocator uses both - <citerefentry><refentrytitle>mmap</refentrytitle> - <manvolnum>2</manvolnum></citerefentry> and - <citerefentry><refentrytitle>sbrk</refentrytitle> - <manvolnum>2</manvolnum></citerefentry>, in that order of preference; - otherwise only <citerefentry><refentrytitle>mmap</refentrytitle> - <manvolnum>2</manvolnum></citerefentry> is used.</para> - - <para>This allocator uses multiple arenas in order to reduce lock - contention for threaded programs on multi-processor systems. This works - well with regard to threading scalability, but incurs some costs. There is - a small fixed per-arena overhead, and additionally, arenas manage memory - completely independently of each other, which means a small fixed increase - in overall memory fragmentation. These overheads are not generally an - issue, given the number of arenas normally used. Note that using - substantially more arenas than the default is not likely to improve - performance, mainly due to reduced cache performance. However, it may make - sense to reduce the number of arenas if an application does not make much - use of the allocation functions.</para> - - <para>In addition to multiple arenas, this allocator supports - thread-specific caching, in order to make it possible to completely avoid - synchronization for most allocation requests. Such caching allows very fast - allocation in the common case, but it increases memory usage and - fragmentation, since a bounded number of objects can remain allocated in - each thread cache.</para> - - <para>Memory is conceptually broken into extents. Extents are always - aligned to multiples of the page size. This alignment makes it possible to - find metadata for user objects quickly. User objects are broken into two - categories according to size: small and large. Contiguous small objects - comprise a slab, which resides within a single extent, whereas large objects - each have their own extents backing them.</para> - - <para>Small objects are managed in groups by slabs. Each slab maintains - a bitmap to track which regions are in use. Allocation requests that are no - more than half the quantum (8 or 16, depending on architecture) are rounded - up to the nearest power of two that is at least <code - language="C">sizeof(<type>double</type>)</code>. All other object size - classes are multiples of the quantum, spaced such that there are four size - classes for each doubling in size, which limits internal fragmentation to - approximately 20% for all but the smallest size classes. Small size classes - are smaller than four times the page size, and large size classes extend - from four times the page size up to the largest size class that does not - exceed <constant>PTRDIFF_MAX</constant>.</para> - - <para>Allocations are packed tightly together, which can be an issue for - multi-threaded applications. If you need to assure that allocations do not - suffer from cacheline sharing, round your allocation requests up to the - nearest multiple of the cacheline size, or specify cacheline alignment when - allocating.</para> - - <para>The <function>realloc()</function>, - <function>rallocx()</function>, and - <function>xallocx()</function> functions may resize allocations - without moving them under limited circumstances. Unlike the - <function>*allocx()</function> API, the standard API does not - officially round up the usable size of an allocation to the nearest size - class, so technically it is necessary to call - <function>realloc()</function> to grow e.g. a 9-byte allocation to - 16 bytes, or shrink a 16-byte allocation to 9 bytes. Growth and shrinkage - trivially succeeds in place as long as the pre-size and post-size both round - up to the same size class. No other API guarantees are made regarding - in-place resizing, but the current implementation also tries to resize large - allocations in place, as long as the pre-size and post-size are both large. - For shrinkage to succeed, the extent allocator must support splitting (see - <link - linkend="arena.i.extent_hooks"><mallctl>arena.<i>.extent_hooks</mallctl></link>). - Growth only succeeds if the trailing memory is currently available, and the - extent allocator supports merging.</para> - - <para>Assuming 4 KiB pages and a 16-byte quantum on a 64-bit system, the - size classes in each category are as shown in <xref linkend="size_classes" - xrefstyle="template:Table %n"/>.</para> - - <table xml:id="size_classes" frame="all"> - <title>Size classes</title> - <tgroup cols="3" colsep="1" rowsep="1"> - <colspec colname="c1" align="left"/> - <colspec colname="c2" align="right"/> - <colspec colname="c3" align="left"/> - <thead> - <row> - <entry>Category</entry> - <entry>Spacing</entry> - <entry>Size</entry> - </row> - </thead> - <tbody> - <row> - <entry morerows="8">Small</entry> - <entry>lg</entry> - <entry>[8]</entry> - </row> - <row> - <entry>16</entry> - <entry>[16, 32, 48, 64, 80, 96, 112, 128]</entry> - </row> - <row> - <entry>32</entry> - <entry>[160, 192, 224, 256]</entry> - </row> - <row> - <entry>64</entry> - <entry>[320, 384, 448, 512]</entry> - </row> - <row> - <entry>128</entry> - <entry>[640, 768, 896, 1024]</entry> - </row> - <row> - <entry>256</entry> - <entry>[1280, 1536, 1792, 2048]</entry> - </row> - <row> - <entry>512</entry> - <entry>[2560, 3072, 3584, 4096]</entry> - </row> - <row> - <entry>1 KiB</entry> - <entry>[5 KiB, 6 KiB, 7 KiB, 8 KiB]</entry> - </row> - <row> - <entry>2 KiB</entry> - <entry>[10 KiB, 12 KiB, 14 KiB]</entry> - </row> - <row> - <entry morerows="15">Large</entry> - <entry>2 KiB</entry> - <entry>[16 KiB]</entry> - </row> - <row> - <entry>4 KiB</entry> - <entry>[20 KiB, 24 KiB, 28 KiB, 32 KiB]</entry> - </row> - <row> - <entry>8 KiB</entry> - <entry>[40 KiB, 48 KiB, 54 KiB, 64 KiB]</entry> - </row> - <row> - <entry>16 KiB</entry> - <entry>[80 KiB, 96 KiB, 112 KiB, 128 KiB]</entry> - </row> - <row> - <entry>32 KiB</entry> - <entry>[160 KiB, 192 KiB, 224 KiB, 256 KiB]</entry> - </row> - <row> - <entry>64 KiB</entry> - <entry>[320 KiB, 384 KiB, 448 KiB, 512 KiB]</entry> - </row> - <row> - <entry>128 KiB</entry> - <entry>[640 KiB, 768 KiB, 896 KiB, 1 MiB]</entry> - </row> - <row> - <entry>256 KiB</entry> - <entry>[1280 KiB, 1536 KiB, 1792 KiB, 2 MiB]</entry> - </row> - <row> - <entry>512 KiB</entry> - <entry>[2560 KiB, 3 MiB, 3584 KiB, 4 MiB]</entry> - </row> - <row> - <entry>1 MiB</entry> - <entry>[5 MiB, 6 MiB, 7 MiB, 8 MiB]</entry> - </row> - <row> - <entry>2 MiB</entry> - <entry>[10 MiB, 12 MiB, 14 MiB, 16 MiB]</entry> - </row> - <row> - <entry>4 MiB</entry> - <entry>[20 MiB, 24 MiB, 28 MiB, 32 MiB]</entry> - </row> - <row> - <entry>8 MiB</entry> - <entry>[40 MiB, 48 MiB, 56 MiB, 64 MiB]</entry> - </row> - <row> - <entry>...</entry> - <entry>...</entry> - </row> - <row> - <entry>512 PiB</entry> - <entry>[2560 PiB, 3 EiB, 3584 PiB, 4 EiB]</entry> - </row> - <row> - <entry>1 EiB</entry> - <entry>[5 EiB, 6 EiB, 7 EiB]</entry> - </row> - </tbody> - </tgroup> - </table> - </refsect1> - <refsect1 id="mallctl_namespace"> - <title>MALLCTL NAMESPACE</title> - <para>The following names are defined in the namespace accessible via the - <function>mallctl*()</function> functions. Value types are specified in - parentheses, their readable/writable statuses are encoded as - <literal>rw</literal>, <literal>r-</literal>, <literal>-w</literal>, or - <literal>--</literal>, and required build configuration flags follow, if - any. A name element encoded as <literal><i></literal> or - <literal><j></literal> indicates an integer component, where the - integer varies from 0 to some upper value that must be determined via - introspection. In the case of <mallctl>stats.arenas.<i>.*</mallctl> - and <mallctl>arena.<i>.{initialized,purge,decay,dss}</mallctl>, - <literal><i></literal> equal to - <constant>MALLCTL_ARENAS_ALL</constant> can be used to operate on all arenas - or access the summation of statistics from all arenas; similarly - <literal><i></literal> equal to - <constant>MALLCTL_ARENAS_DESTROYED</constant> can be used to access the - summation of statistics from all destroyed arenas. These constants can be - utilized either via <function>mallctlnametomib()</function> followed by - <function>mallctlbymib()</function>, or via code such as the following: - <programlisting language="C"><![CDATA[ -#define STRINGIFY_HELPER(x) #x -#define STRINGIFY(x) STRINGIFY_HELPER(x) - -mallctl("arena." STRINGIFY(MALLCTL_ARENAS_ALL) ".decay", - NULL, NULL, NULL, 0);]]></programlisting> - Take special note of the <link - linkend="epoch"><mallctl>epoch</mallctl></link> mallctl, which controls - refreshing of cached dynamic statistics.</para> - - <variablelist> - <varlistentry id="version"> - <term> - <mallctl>version</mallctl> - (<type>const char *</type>) - <literal>r-</literal> - </term> - <listitem><para>Return the jemalloc version string.</para></listitem> - </varlistentry> - - <varlistentry id="epoch"> - <term> - <mallctl>epoch</mallctl> - (<type>uint64_t</type>) - <literal>rw</literal> - </term> - <listitem><para>If a value is passed in, refresh the data from which - the <function>mallctl*()</function> functions report values, - and increment the epoch. Return the current epoch. This is useful for - detecting whether another thread caused a refresh.</para></listitem> - </varlistentry> - - <varlistentry id="background_thread"> - <term> - <mallctl>background_thread</mallctl> - (<type>bool</type>) - <literal>rw</literal> - </term> - <listitem><para>Enable/disable internal background worker threads. When - set to true, background threads are created on demand (the number of - background threads will be no more than the number of CPUs or active - arenas). Threads run periodically, and handle <link - linkend="arena.i.decay">purging</link> asynchronously. When switching - off, background threads are terminated synchronously. Note that after - <citerefentry><refentrytitle>fork</refentrytitle><manvolnum>2</manvolnum></citerefentry> - function, the state in the child process will be disabled regardless - the state in parent process. See <link - linkend="stats.background_thread.num_threads"><mallctl>stats.background_thread</mallctl></link> - for related stats. <link - linkend="opt.background_thread"><mallctl>opt.background_thread</mallctl></link> - can be used to set the default option. This option is only available on - selected pthread-based platforms.</para></listitem> - </varlistentry> - - <varlistentry id="max_background_threads"> - <term> - <mallctl>max_background_threads</mallctl> - (<type>size_t</type>) - <literal>rw</literal> - </term> - <listitem><para>Maximum number of background worker threads that will - be created. This value is capped at <link - linkend="opt.max_background_threads"><mallctl>opt.max_background_threads</mallctl></link> at - startup.</para></listitem> - </varlistentry> - - <varlistentry id="config.cache_oblivious"> - <term> - <mallctl>config.cache_oblivious</mallctl> - (<type>bool</type>) - <literal>r-</literal> - </term> - <listitem><para><option>--enable-cache-oblivious</option> was specified - during build configuration.</para></listitem> - </varlistentry> - - <varlistentry id="config.debug"> - <term> - <mallctl>config.debug</mallctl> - (<type>bool</type>) - <literal>r-</literal> - </term> - <listitem><para><option>--enable-debug</option> was specified during - build configuration.</para></listitem> - </varlistentry> - - <varlistentry id="config.fill"> - <term> - <mallctl>config.fill</mallctl> - (<type>bool</type>) - <literal>r-</literal> - </term> - <listitem><para><option>--enable-fill</option> was specified during - build configuration.</para></listitem> - </varlistentry> - - <varlistentry id="config.lazy_lock"> - <term> - <mallctl>config.lazy_lock</mallctl> - (<type>bool</type>) - <literal>r-</literal> - </term> - <listitem><para><option>--enable-lazy-lock</option> was specified - during build configuration.</para></listitem> - </varlistentry> - - <varlistentry id="config.malloc_conf"> - <term> - <mallctl>config.malloc_conf</mallctl> - (<type>const char *</type>) - <literal>r-</literal> - </term> - <listitem><para>Embedded configure-time-specified run-time options - string, empty unless <option>--with-malloc-conf</option> was specified - during build configuration.</para></listitem> - </varlistentry> - - <varlistentry id="config.prof"> - <term> - <mallctl>config.prof</mallctl> - (<type>bool</type>) - <literal>r-</literal> - </term> - <listitem><para><option>--enable-prof</option> was specified during - build configuration.</para></listitem> - </varlistentry> - - <varlistentry id="config.prof_libgcc"> - <term> - <mallctl>config.prof_libgcc</mallctl> - (<type>bool</type>) - <literal>r-</literal> - </term> - <listitem><para><option>--disable-prof-libgcc</option> was not - specified during build configuration.</para></listitem> - </varlistentry> - - <varlistentry id="config.prof_libunwind"> - <term> - <mallctl>config.prof_libunwind</mallctl> - (<type>bool</type>) - <literal>r-</literal> - </term> - <listitem><para><option>--enable-prof-libunwind</option> was specified - during build configuration.</para></listitem> - </varlistentry> - - <varlistentry id="config.stats"> - <term> - <mallctl>config.stats</mallctl> - (<type>bool</type>) - <literal>r-</literal> - </term> - <listitem><para><option>--enable-stats</option> was specified during - build configuration.</para></listitem> - </varlistentry> - - - <varlistentry id="config.utrace"> - <term> - <mallctl>config.utrace</mallctl> - (<type>bool</type>) - <literal>r-</literal> - </term> - <listitem><para><option>--enable-utrace</option> was specified during - build configuration.</para></listitem> - </varlistentry> - - <varlistentry id="config.xmalloc"> - <term> - <mallctl>config.xmalloc</mallctl> - (<type>bool</type>) - <literal>r-</literal> - </term> - <listitem><para><option>--enable-xmalloc</option> was specified during - build configuration.</para></listitem> - </varlistentry> - - <varlistentry id="opt.abort"> - <term> - <mallctl>opt.abort</mallctl> - (<type>bool</type>) - <literal>r-</literal> - </term> - <listitem><para>Abort-on-warning enabled/disabled. If true, most - warnings are fatal. Note that runtime option warnings are not included - (see <link - linkend="opt.abort_conf"><mallctl>opt.abort_conf</mallctl></link> for - that). The process will call - <citerefentry><refentrytitle>abort</refentrytitle> - <manvolnum>3</manvolnum></citerefentry> in these cases. This option is - disabled by default unless <option>--enable-debug</option> is - specified during configuration, in which case it is enabled by default. - </para></listitem> - </varlistentry> - - <varlistentry id="opt.confirm_conf"> - <term> - <mallctl>opt.confirm_conf</mallctl> - (<type>bool</type>) - <literal>r-</literal> - </term> - <listitem><para>Confirm-runtime-options-when-program-starts - enabled/disabled. If true, the string specified via - <option>--with-malloc-conf</option>, the string pointed to by the - global variable <varname>malloc_conf</varname>, the <quote>name</quote> - of the file referenced by the symbolic link named - <filename class="symlink">/etc/malloc.conf</filename>, and the value of - the environment variable <envar>MALLOC_CONF</envar>, will be printed in - order. Then, each option being set will be individually printed. This - option is disabled by default.</para></listitem> - </varlistentry> - - <varlistentry id="opt.abort_conf"> - <term> - <mallctl>opt.abort_conf</mallctl> - (<type>bool</type>) - <literal>r-</literal> - </term> - <listitem><para>Abort-on-invalid-configuration enabled/disabled. If - true, invalid runtime options are fatal. The process will call - <citerefentry><refentrytitle>abort</refentrytitle> - <manvolnum>3</manvolnum></citerefentry> in these cases. This option is - disabled by default unless <option>--enable-debug</option> is - specified during configuration, in which case it is enabled by default. - </para></listitem> - </varlistentry> - - <varlistentry id="opt.metadata_thp"> - <term> - <mallctl>opt.metadata_thp</mallctl> - (<type>const char *</type>) - <literal>r-</literal> - </term> - <listitem><para>Controls whether to allow jemalloc to use transparent - huge page (THP) for internal metadata (see <link - linkend="stats.metadata">stats.metadata</link>). <quote>always</quote> - allows such usage. <quote>auto</quote> uses no THP initially, but may - begin to do so when metadata usage reaches certain level. The default - is <quote>disabled</quote>.</para></listitem> - </varlistentry> - - <varlistentry id="opt.retain"> - <term> - <mallctl>opt.retain</mallctl> - (<type>bool</type>) - <literal>r-</literal> - </term> - <listitem><para>If true, retain unused virtual memory for later reuse - rather than discarding it by calling - <citerefentry><refentrytitle>munmap</refentrytitle> - <manvolnum>2</manvolnum></citerefentry> or equivalent (see <link - linkend="stats.retained">stats.retained</link> for related details). - It also makes jemalloc use <citerefentry> - <refentrytitle>mmap</refentrytitle><manvolnum>2</manvolnum> - </citerefentry> or equivalent in a more greedy way, mapping larger - chunks in one go. This option is disabled by default unless discarding - virtual memory is known to trigger platform-specific performance - problems, namely 1) for [64-bit] Linux, which has a quirk in its virtual - memory allocation algorithm that causes semi-permanent VM map holes - under normal jemalloc operation; and 2) for [64-bit] Windows, which - disallows split / merged regions with - <parameter><constant>MEM_RELEASE</constant></parameter>. Although the - same issues may present on 32-bit platforms as well, retaining virtual - memory for 32-bit Linux and Windows is disabled by default due to the - practical possibility of address space exhaustion. </para></listitem> - </varlistentry> - - <varlistentry id="opt.dss"> - <term> - <mallctl>opt.dss</mallctl> - (<type>const char *</type>) - <literal>r-</literal> - </term> - <listitem><para>dss (<citerefentry><refentrytitle>sbrk</refentrytitle> - <manvolnum>2</manvolnum></citerefentry>) allocation precedence as - related to <citerefentry><refentrytitle>mmap</refentrytitle> - <manvolnum>2</manvolnum></citerefentry> allocation. The following - settings are supported if - <citerefentry><refentrytitle>sbrk</refentrytitle> - <manvolnum>2</manvolnum></citerefentry> is supported by the operating - system: <quote>disabled</quote>, <quote>primary</quote>, and - <quote>secondary</quote>; otherwise only <quote>disabled</quote> is - supported. The default is <quote>secondary</quote> if - <citerefentry><refentrytitle>sbrk</refentrytitle> - <manvolnum>2</manvolnum></citerefentry> is supported by the operating - system; <quote>disabled</quote> otherwise. - </para></listitem> - </varlistentry> - - <varlistentry id="opt.narenas"> - <term> - <mallctl>opt.narenas</mallctl> - (<type>unsigned</type>) - <literal>r-</literal> - </term> - <listitem><para>Maximum number of arenas to use for automatic - multiplexing of threads and arenas. The default is four times the - number of CPUs, or one if there is a single CPU.</para></listitem> - </varlistentry> - - <varlistentry id="opt.oversize_threshold"> - <term> - <mallctl>opt.oversize_threshold</mallctl> - (<type>size_t</type>) - <literal>r-</literal> - </term> - <listitem><para>The threshold in bytes of which requests are considered - oversize. Allocation requests with greater sizes are fulfilled from a - dedicated arena (automatically managed, however not within - <literal>narenas</literal>), in order to reduce fragmentation by not - mixing huge allocations with small ones. In addition, the decay API - guarantees on the extents greater than the specified threshold may be - overridden. Note that requests with arena index specified via - <constant>MALLOCX_ARENA</constant>, or threads associated with explicit - arenas will not be considered. The default threshold is 8MiB. Values - not within large size classes disables this feature.</para></listitem> - </varlistentry> - - <varlistentry id="opt.percpu_arena"> - <term> - <mallctl>opt.percpu_arena</mallctl> - (<type>const char *</type>) - <literal>r-</literal> - </term> - <listitem><para>Per CPU arena mode. Use the <quote>percpu</quote> - setting to enable this feature, which uses number of CPUs to determine - number of arenas, and bind threads to arenas dynamically based on the - CPU the thread runs on currently. <quote>phycpu</quote> setting uses - one arena per physical CPU, which means the two hyper threads on the - same CPU share one arena. Note that no runtime checking regarding the - availability of hyper threading is done at the moment. When set to - <quote>disabled</quote>, narenas and thread to arena association will - not be impacted by this option. The default is <quote>disabled</quote>. - </para></listitem> - </varlistentry> - - <varlistentry id="opt.background_thread"> - <term> - <mallctl>opt.background_thread</mallctl> - (<type>bool</type>) - <literal>r-</literal> - </term> - <listitem><para>Internal background worker threads enabled/disabled. - Because of potential circular dependencies, enabling background thread - using this option may cause crash or deadlock during initialization. For - a reliable way to use this feature, see <link - linkend="background_thread">background_thread</link> for dynamic control - options and details. This option is disabled by - default.</para></listitem> - </varlistentry> - - <varlistentry id="opt.max_background_threads"> - <term> - <mallctl>opt.max_background_threads</mallctl> - (<type>size_t</type>) - <literal>r-</literal> - </term> - <listitem><para>Maximum number of background threads that will be created - if <link linkend="background_thread">background_thread</link> is set. - Defaults to number of cpus.</para></listitem> - </varlistentry> - - <varlistentry id="opt.dirty_decay_ms"> - <term> - <mallctl>opt.dirty_decay_ms</mallctl> - (<type>ssize_t</type>) - <literal>r-</literal> - </term> - <listitem><para>Approximate time in milliseconds from the creation of a - set of unused dirty pages until an equivalent set of unused dirty pages - is purged (i.e. converted to muzzy via e.g. - <function>madvise(<parameter>...</parameter><parameter><constant>MADV_FREE</constant></parameter>)</function> - if supported by the operating system, or converted to clean otherwise) - and/or reused. Dirty pages are defined as previously having been - potentially written to by the application, and therefore consuming - physical memory, yet having no current use. The pages are incrementally - purged according to a sigmoidal decay curve that starts and ends with - zero purge rate. A decay time of 0 causes all unused dirty pages to be - purged immediately upon creation. A decay time of -1 disables purging. - The default decay time is 10 seconds. See <link - linkend="arenas.dirty_decay_ms"><mallctl>arenas.dirty_decay_ms</mallctl></link> - and <link - linkend="arena.i.dirty_decay_ms"><mallctl>arena.<i>.dirty_decay_ms</mallctl></link> - for related dynamic control options. See <link - linkend="opt.muzzy_decay_ms"><mallctl>opt.muzzy_decay_ms</mallctl></link> - for a description of muzzy pages.for a description of muzzy pages. Note - that when the <link - linkend="opt.oversize_threshold"><mallctl>oversize_threshold</mallctl></link> - feature is enabled, the arenas reserved for oversize requests may have - its own default decay settings.</para></listitem> - </varlistentry> - - <varlistentry id="opt.muzzy_decay_ms"> - <term> - <mallctl>opt.muzzy_decay_ms</mallctl> - (<type>ssize_t</type>) - <literal>r-</literal> - </term> - <listitem><para>Approximate time in milliseconds from the creation of a - set of unused muzzy pages until an equivalent set of unused muzzy pages - is purged (i.e. converted to clean) and/or reused. Muzzy pages are - defined as previously having been unused dirty pages that were - subsequently purged in a manner that left them subject to the - reclamation whims of the operating system (e.g. - <function>madvise(<parameter>...</parameter><parameter><constant>MADV_FREE</constant></parameter>)</function>), - and therefore in an indeterminate state. The pages are incrementally - purged according to a sigmoidal decay curve that starts and ends with - zero purge rate. A decay time of 0 causes all unused muzzy pages to be - purged immediately upon creation. A decay time of -1 disables purging. - The default decay time is 10 seconds. See <link - linkend="arenas.muzzy_decay_ms"><mallctl>arenas.muzzy_decay_ms</mallctl></link> - and <link - linkend="arena.i.muzzy_decay_ms"><mallctl>arena.<i>.muzzy_decay_ms</mallctl></link> - for related dynamic control options.</para></listitem> - </varlistentry> - - <varlistentry id="opt.lg_extent_max_active_fit"> - <term> - <mallctl>opt.lg_extent_max_active_fit</mallctl> - (<type>size_t</type>) - <literal>r-</literal> - </term> - <listitem><para>When reusing dirty extents, this determines the (log - base 2 of the) maximum ratio between the size of the active extent - selected (to split off from) and the size of the requested allocation. - This prevents the splitting of large active extents for smaller - allocations, which can reduce fragmentation over the long run - (especially for non-active extents). Lower value may reduce - fragmentation, at the cost of extra active extents. The default value - is 6, which gives a maximum ratio of 64 (2^6).</para></listitem> - </varlistentry> - - <varlistentry id="opt.stats_print"> - <term> - <mallctl>opt.stats_print</mallctl> - (<type>bool</type>) - <literal>r-</literal> - </term> - <listitem><para>Enable/disable statistics printing at exit. If - enabled, the <function>malloc_stats_print()</function> - function is called at program exit via an - <citerefentry><refentrytitle>atexit</refentrytitle> - <manvolnum>3</manvolnum></citerefentry> function. <link - linkend="opt.stats_print_opts"><mallctl>opt.stats_print_opts</mallctl></link> - can be combined to specify output options. If - <option>--enable-stats</option> is specified during configuration, this - has the potential to cause deadlock for a multi-threaded process that - exits while one or more threads are executing in the memory allocation - functions. Furthermore, <function>atexit()</function> may - allocate memory during application initialization and then deadlock - internally when jemalloc in turn calls - <function>atexit()</function>, so this option is not - universally usable (though the application can register its own - <function>atexit()</function> function with equivalent - functionality). Therefore, this option should only be used with care; - it is primarily intended as a performance tuning aid during application - development. This option is disabled by default.</para></listitem> - </varlistentry> - - <varlistentry id="opt.stats_print_opts"> - <term> - <mallctl>opt.stats_print_opts</mallctl> - (<type>const char *</type>) - <literal>r-</literal> - </term> - <listitem><para>Options (the <parameter>opts</parameter> string) to pass - to the <function>malloc_stats_print()</function> at exit (enabled - through <link - linkend="opt.stats_print"><mallctl>opt.stats_print</mallctl></link>). See - available options in <link - linkend="malloc_stats_print_opts"><function>malloc_stats_print()</function></link>. - Has no effect unless <link - linkend="opt.stats_print"><mallctl>opt.stats_print</mallctl></link> is - enabled. The default is <quote></quote>.</para></listitem> - </varlistentry> - - <varlistentry id="opt.junk"> - <term> - <mallctl>opt.junk</mallctl> - (<type>const char *</type>) - <literal>r-</literal> - [<option>--enable-fill</option>] - </term> - <listitem><para>Junk filling. If set to <quote>alloc</quote>, each byte - of uninitialized allocated memory will be initialized to - <literal>0xa5</literal>. If set to <quote>free</quote>, all deallocated - memory will be initialized to <literal>0x5a</literal>. If set to - <quote>true</quote>, both allocated and deallocated memory will be - initialized, and if set to <quote>false</quote>, junk filling be - disabled entirely. This is intended for debugging and will impact - performance negatively. This option is <quote>false</quote> by default - unless <option>--enable-debug</option> is specified during - configuration, in which case it is <quote>true</quote> by - default.</para></listitem> - </varlistentry> - - <varlistentry id="opt.zero"> - <term> - <mallctl>opt.zero</mallctl> - (<type>bool</type>) - <literal>r-</literal> - [<option>--enable-fill</option>] - </term> - <listitem><para>Zero filling enabled/disabled. If enabled, each byte - of uninitialized allocated memory will be initialized to 0. Note that - this initialization only happens once for each byte, so - <function>realloc()</function> and - <function>rallocx()</function> calls do not zero memory that - was previously allocated. This is intended for debugging and will - impact performance negatively. This option is disabled by default. - </para></listitem> - </varlistentry> - - <varlistentry id="opt.utrace"> - <term> - <mallctl>opt.utrace</mallctl> - (<type>bool</type>) - <literal>r-</literal> - [<option>--enable-utrace</option>] - </term> - <listitem><para>Allocation tracing based on - <citerefentry><refentrytitle>utrace</refentrytitle> - <manvolnum>2</manvolnum></citerefentry> enabled/disabled. This option - is disabled by default.</para></listitem> - </varlistentry> - - <varlistentry id="opt.xmalloc"> - <term> - <mallctl>opt.xmalloc</mallctl> - (<type>bool</type>) - <literal>r-</literal> - [<option>--enable-xmalloc</option>] - </term> - <listitem><para>Abort-on-out-of-memory enabled/disabled. If enabled, - rather than returning failure for any allocation function, display a - diagnostic message on <constant>STDERR_FILENO</constant> and cause the - program to drop core (using - <citerefentry><refentrytitle>abort</refentrytitle> - <manvolnum>3</manvolnum></citerefentry>). If an application is - designed to depend on this behavior, set the option at compile time by - including the following in the source code: - <programlisting language="C"><![CDATA[ -malloc_conf = "xmalloc:true";]]></programlisting> - This option is disabled by default.</para></listitem> - </varlistentry> - - <varlistentry id="opt.tcache"> - <term> - <mallctl>opt.tcache</mallctl> - (<type>bool</type>) - <literal>r-</literal> - </term> - <listitem><para>Thread-specific caching (tcache) enabled/disabled. When - there are multiple threads, each thread uses a tcache for objects up to - a certain size. Thread-specific caching allows many allocations to be - satisfied without performing any thread synchronization, at the cost of - increased memory use. See the <link - linkend="opt.lg_tcache_max"><mallctl>opt.lg_tcache_max</mallctl></link> - option for related tuning information. This option is enabled by - default.</para></listitem> - </varlistentry> - - <varlistentry id="opt.lg_tcache_max"> - <term> - <mallctl>opt.lg_tcache_max</mallctl> - (<type>size_t</type>) - <literal>r-</literal> - </term> - <listitem><para>Maximum size class (log base 2) to cache in the - thread-specific cache (tcache). At a minimum, all small size classes - are cached, and at a maximum all large size classes are cached. The - default maximum is 32 KiB (2^15).</para></listitem> - </varlistentry> - - <varlistentry id="opt.thp"> - <term> - <mallctl>opt.thp</mallctl> - (<type>const char *</type>) - <literal>r-</literal> - </term> - <listitem><para>Transparent hugepage (THP) mode. Settings "always", - "never" and "default" are available if THP is supported by the operating - system. The "always" setting enables transparent hugepage for all user - memory mappings with - <parameter><constant>MADV_HUGEPAGE</constant></parameter>; "never" - ensures no transparent hugepage with - <parameter><constant>MADV_NOHUGEPAGE</constant></parameter>; the default - setting "default" makes no changes. Note that: this option does not - affect THP for jemalloc internal metadata (see <link - linkend="opt.metadata_thp"><mallctl>opt.metadata_thp</mallctl></link>); - in addition, for arenas with customized <link - linkend="arena.i.extent_hooks"><mallctl>extent_hooks</mallctl></link>, - this option is bypassed as it is implemented as part of the default - extent hooks.</para></listitem> - </varlistentry> - - <varlistentry id="opt.prof"> - <term> - <mallctl>opt.prof</mallctl> - (<type>bool</type>) - <literal>r-</literal> - [<option>--enable-prof</option>] - </term> - <listitem><para>Memory profiling enabled/disabled. If enabled, profile - memory allocation activity. See the <link - linkend="opt.prof_active"><mallctl>opt.prof_active</mallctl></link> - option for on-the-fly activation/deactivation. See the <link - linkend="opt.lg_prof_sample"><mallctl>opt.lg_prof_sample</mallctl></link> - option for probabilistic sampling control. See the <link - linkend="opt.prof_accum"><mallctl>opt.prof_accum</mallctl></link> - option for control of cumulative sample reporting. See the <link - linkend="opt.lg_prof_interval"><mallctl>opt.lg_prof_interval</mallctl></link> - option for information on interval-triggered profile dumping, the <link - linkend="opt.prof_gdump"><mallctl>opt.prof_gdump</mallctl></link> - option for information on high-water-triggered profile dumping, and the - <link linkend="opt.prof_final"><mallctl>opt.prof_final</mallctl></link> - option for final profile dumping. Profile output is compatible with - the <command>jeprof</command> command, which is based on the - <command>pprof</command> that is developed as part of the <ulink - url="http://code.google.com/p/gperftools/">gperftools - package</ulink>. See <link linkend="heap_profile_format">HEAP PROFILE - FORMAT</link> for heap profile format documentation.</para></listitem> - </varlistentry> - - <varlistentry id="opt.prof_prefix"> - <term> - <mallctl>opt.prof_prefix</mallctl> - (<type>const char *</type>) - <literal>r-</literal> - [<option>--enable-prof</option>] - </term> - <listitem><para>Filename prefix for profile dumps. If the prefix is - set to the empty string, no automatic dumps will occur; this is - primarily useful for disabling the automatic final heap dump (which - also disables leak reporting, if enabled). The default prefix is - <filename>jeprof</filename>.</para></listitem> - </varlistentry> - - <varlistentry id="opt.prof_active"> - <term> - <mallctl>opt.prof_active</mallctl> - (<type>bool</type>) - <literal>r-</literal> - [<option>--enable-prof</option>] - </term> - <listitem><para>Profiling activated/deactivated. This is a secondary - control mechanism that makes it possible to start the application with - profiling enabled (see the <link - linkend="opt.prof"><mallctl>opt.prof</mallctl></link> option) but - inactive, then toggle profiling at any time during program execution - with the <link - linkend="prof.active"><mallctl>prof.active</mallctl></link> mallctl. - This option is enabled by default.</para></listitem> - </varlistentry> - - <varlistentry id="opt.prof_thread_active_init"> - <term> - <mallctl>opt.prof_thread_active_init</mallctl> - (<type>bool</type>) - <literal>r-</literal> - [<option>--enable-prof</option>] - </term> - <listitem><para>Initial setting for <link - linkend="thread.prof.active"><mallctl>thread.prof.active</mallctl></link> - in newly created threads. The initial setting for newly created threads - can also be changed during execution via the <link - linkend="prof.thread_active_init"><mallctl>prof.thread_active_init</mallctl></link> - mallctl. This option is enabled by default.</para></listitem> - </varlistentry> - - <varlistentry id="opt.lg_prof_sample"> - <term> - <mallctl>opt.lg_prof_sample</mallctl> - (<type>size_t</type>) - <literal>r-</literal> - [<option>--enable-prof</option>] - </term> - <listitem><para>Average interval (log base 2) between allocation - samples, as measured in bytes of allocation activity. Increasing the - sampling interval decreases profile fidelity, but also decreases the - computational overhead. The default sample interval is 512 KiB (2^19 - B).</para></listitem> - </varlistentry> - - <varlistentry id="opt.prof_accum"> - <term> - <mallctl>opt.prof_accum</mallctl> - (<type>bool</type>) - <literal>r-</literal> - [<option>--enable-prof</option>] - </term> - <listitem><para>Reporting of cumulative object/byte counts in profile - dumps enabled/disabled. If this option is enabled, every unique - backtrace must be stored for the duration of execution. Depending on - the application, this can impose a large memory overhead, and the - cumulative counts are not always of interest. This option is disabled - by default.</para></listitem> - </varlistentry> - - <varlistentry id="opt.lg_prof_interval"> - <term> - <mallctl>opt.lg_prof_interval</mallctl> - (<type>ssize_t</type>) - <literal>r-</literal> - [<option>--enable-prof</option>] - </term> - <listitem><para>Average interval (log base 2) between memory profile - dumps, as measured in bytes of allocation activity. The actual - interval between dumps may be sporadic because decentralized allocation - counters are used to avoid synchronization bottlenecks. Profiles are - dumped to files named according to the pattern - <filename><prefix>.<pid>.<seq>.i<iseq>.heap</filename>, - where <literal><prefix></literal> is controlled by the - <link - linkend="opt.prof_prefix"><mallctl>opt.prof_prefix</mallctl></link> - option. By default, interval-triggered profile dumping is disabled - (encoded as -1). - </para></listitem> - </varlistentry> - - <varlistentry id="opt.prof_gdump"> - <term> - <mallctl>opt.prof_gdump</mallctl> - (<type>bool</type>) - <literal>r-</literal> - [<option>--enable-prof</option>] - </term> - <listitem><para>Set the initial state of <link - linkend="prof.gdump"><mallctl>prof.gdump</mallctl></link>, which when - enabled triggers a memory profile dump every time the total virtual - memory exceeds the previous maximum. This option is disabled by - default.</para></listitem> - </varlistentry> - - <varlistentry id="opt.prof_final"> - <term> - <mallctl>opt.prof_final</mallctl> - (<type>bool</type>) - <literal>r-</literal> - [<option>--enable-prof</option>] - </term> - <listitem><para>Use an - <citerefentry><refentrytitle>atexit</refentrytitle> - <manvolnum>3</manvolnum></citerefentry> function to dump final memory - usage to a file named according to the pattern - <filename><prefix>.<pid>.<seq>.f.heap</filename>, - where <literal><prefix></literal> is controlled by the <link - linkend="opt.prof_prefix"><mallctl>opt.prof_prefix</mallctl></link> - option. Note that <function>atexit()</function> may allocate - memory during application initialization and then deadlock internally - when jemalloc in turn calls <function>atexit()</function>, so - this option is not universally usable (though the application can - register its own <function>atexit()</function> function with - equivalent functionality). This option is disabled by - default.</para></listitem> - </varlistentry> - - <varlistentry id="opt.prof_leak"> - <term> - <mallctl>opt.prof_leak</mallctl> - (<type>bool</type>) - <literal>r-</literal> - [<option>--enable-prof</option>] - </term> - <listitem><para>Leak reporting enabled/disabled. If enabled, use an - <citerefentry><refentrytitle>atexit</refentrytitle> - <manvolnum>3</manvolnum></citerefentry> function to report memory leaks - detected by allocation sampling. See the - <link linkend="opt.prof"><mallctl>opt.prof</mallctl></link> option for - information on analyzing heap profile output. This option is disabled - by default.</para></listitem> - </varlistentry> - - <varlistentry id="thread.arena"> - <term> - <mallctl>thread.arena</mallctl> - (<type>unsigned</type>) - <literal>rw</literal> - </term> - <listitem><para>Get or set the arena associated with the calling - thread. If the specified arena was not initialized beforehand (see the - <link - linkend="arena.i.initialized"><mallctl>arena.i.initialized</mallctl></link> - mallctl), it will be automatically initialized as a side effect of - calling this interface.</para></listitem> - </varlistentry> - - <varlistentry id="thread.allocated"> - <term> - <mallctl>thread.allocated</mallctl> - (<type>uint64_t</type>) - <literal>r-</literal> - [<option>--enable-stats</option>] - </term> - <listitem><para>Get the total number of bytes ever allocated by the - calling thread. This counter has the potential to wrap around; it is - up to the application to appropriately interpret the counter in such - cases.</para></listitem> - </varlistentry> - - <varlistentry id="thread.allocatedp"> - <term> - <mallctl>thread.allocatedp</mallctl> - (<type>uint64_t *</type>) - <literal>r-</literal> - [<option>--enable-stats</option>] - </term> - <listitem><para>Get a pointer to the the value that is returned by the - <link - linkend="thread.allocated"><mallctl>thread.allocated</mallctl></link> - mallctl. This is useful for avoiding the overhead of repeated - <function>mallctl*()</function> calls.</para></listitem> - </varlistentry> - - <varlistentry id="thread.deallocated"> - <term> - <mallctl>thread.deallocated</mallctl> - (<type>uint64_t</type>) - <literal>r-</literal> - [<option>--enable-stats</option>] - </term> - <listitem><para>Get the total number of bytes ever deallocated by the - calling thread. This counter has the potential to wrap around; it is - up to the application to appropriately interpret the counter in such - cases.</para></listitem> - </varlistentry> - - <varlistentry id="thread.deallocatedp"> - <term> - <mallctl>thread.deallocatedp</mallctl> - (<type>uint64_t *</type>) - <literal>r-</literal> - [<option>--enable-stats</option>] - </term> - <listitem><para>Get a pointer to the the value that is returned by the - <link - linkend="thread.deallocated"><mallctl>thread.deallocated</mallctl></link> - mallctl. This is useful for avoiding the overhead of repeated - <function>mallctl*()</function> calls.</para></listitem> - </varlistentry> - - <varlistentry id="thread.tcache.enabled"> - <term> - <mallctl>thread.tcache.enabled</mallctl> - (<type>bool</type>) - <literal>rw</literal> - </term> - <listitem><para>Enable/disable calling thread's tcache. The tcache is - implicitly flushed as a side effect of becoming - disabled (see <link - linkend="thread.tcache.flush"><mallctl>thread.tcache.flush</mallctl></link>). - </para></listitem> - </varlistentry> - - <varlistentry id="thread.tcache.flush"> - <term> - <mallctl>thread.tcache.flush</mallctl> - (<type>void</type>) - <literal>--</literal> - </term> - <listitem><para>Flush calling thread's thread-specific cache (tcache). - This interface releases all cached objects and internal data structures - associated with the calling thread's tcache. Ordinarily, this interface - need not be called, since automatic periodic incremental garbage - collection occurs, and the thread cache is automatically discarded when - a thread exits. However, garbage collection is triggered by allocation - activity, so it is possible for a thread that stops - allocating/deallocating to retain its cache indefinitely, in which case - the developer may find manual flushing useful.</para></listitem> - </varlistentry> - - <varlistentry id="thread.prof.name"> - <term> - <mallctl>thread.prof.name</mallctl> - (<type>const char *</type>) - <literal>r-</literal> or - <literal>-w</literal> - [<option>--enable-prof</option>] - </term> - <listitem><para>Get/set the descriptive name associated with the calling - thread in memory profile dumps. An internal copy of the name string is - created, so the input string need not be maintained after this interface - completes execution. The output string of this interface should be - copied for non-ephemeral uses, because multiple implementation details - can cause asynchronous string deallocation. Furthermore, each - invocation of this interface can only read or write; simultaneous - read/write is not supported due to string lifetime limitations. The - name string must be nil-terminated and comprised only of characters in - the sets recognized - by <citerefentry><refentrytitle>isgraph</refentrytitle> - <manvolnum>3</manvolnum></citerefentry> and - <citerefentry><refentrytitle>isblank</refentrytitle> - <manvolnum>3</manvolnum></citerefentry>.</para></listitem> - </varlistentry> - - <varlistentry id="thread.prof.active"> - <term> - <mallctl>thread.prof.active</mallctl> - (<type>bool</type>) - <literal>rw</literal> - [<option>--enable-prof</option>] - </term> - <listitem><para>Control whether sampling is currently active for the - calling thread. This is an activation mechanism in addition to <link - linkend="prof.active"><mallctl>prof.active</mallctl></link>; both must - be active for the calling thread to sample. This flag is enabled by - default.</para></listitem> - </varlistentry> - - <varlistentry id="tcache.create"> - <term> - <mallctl>tcache.create</mallctl> - (<type>unsigned</type>) - <literal>r-</literal> - </term> - <listitem><para>Create an explicit thread-specific cache (tcache) and - return an identifier that can be passed to the <link - linkend="MALLOCX_TCACHE"><constant>MALLOCX_TCACHE(<parameter>tc</parameter>)</constant></link> - macro to explicitly use the specified cache rather than the - automatically managed one that is used by default. Each explicit cache - can be used by only one thread at a time; the application must assure - that this constraint holds. - </para></listitem> - </varlistentry> - - <varlistentry id="tcache.flush"> - <term> - <mallctl>tcache.flush</mallctl> - (<type>unsigned</type>) - <literal>-w</literal> - </term> - <listitem><para>Flush the specified thread-specific cache (tcache). The - same considerations apply to this interface as to <link - linkend="thread.tcache.flush"><mallctl>thread.tcache.flush</mallctl></link>, - except that the tcache will never be automatically discarded. - </para></listitem> - </varlistentry> - - <varlistentry id="tcache.destroy"> - <term> - <mallctl>tcache.destroy</mallctl> - (<type>unsigned</type>) - <literal>-w</literal> - </term> - <listitem><para>Flush the specified thread-specific cache (tcache) and - make the identifier available for use during a future tcache creation. - </para></listitem> - </varlistentry> - - <varlistentry id="arena.i.initialized"> - <term> - <mallctl>arena.<i>.initialized</mallctl> - (<type>bool</type>) - <literal>r-</literal> - </term> - <listitem><para>Get whether the specified arena's statistics are - initialized (i.e. the arena was initialized prior to the current epoch). - This interface can also be nominally used to query whether the merged - statistics corresponding to <constant>MALLCTL_ARENAS_ALL</constant> are - initialized (always true).</para></listitem> - </varlistentry> - - <varlistentry id="arena.i.decay"> - <term> - <mallctl>arena.<i>.decay</mallctl> - (<type>void</type>) - <literal>--</literal> - </term> - <listitem><para>Trigger decay-based purging of unused dirty/muzzy pages - for arena <i>, or for all arenas if <i> equals - <constant>MALLCTL_ARENAS_ALL</constant>. The proportion of unused - dirty/muzzy pages to be purged depends on the current time; see <link - linkend="opt.dirty_decay_ms"><mallctl>opt.dirty_decay_ms</mallctl></link> - and <link - linkend="opt.muzzy_decay_ms"><mallctl>opt.muzy_decay_ms</mallctl></link> - for details.</para></listitem> - </varlistentry> - - <varlistentry id="arena.i.purge"> - <term> - <mallctl>arena.<i>.purge</mallctl> - (<type>void</type>) - <literal>--</literal> - </term> - <listitem><para>Purge all unused dirty pages for arena <i>, or for - all arenas if <i> equals <constant>MALLCTL_ARENAS_ALL</constant>. - </para></listitem> - </varlistentry> - - <varlistentry id="arena.i.reset"> - <term> - <mallctl>arena.<i>.reset</mallctl> - (<type>void</type>) - <literal>--</literal> - </term> - <listitem><para>Discard all of the arena's extant allocations. This - interface can only be used with arenas explicitly created via <link - linkend="arenas.create"><mallctl>arenas.create</mallctl></link>. None - of the arena's discarded/cached allocations may accessed afterward. As - part of this requirement, all thread caches which were used to - allocate/deallocate in conjunction with the arena must be flushed - beforehand.</para></listitem> - </varlistentry> - - <varlistentry id="arena.i.destroy"> - <term> - <mallctl>arena.<i>.destroy</mallctl> - (<type>void</type>) - <literal>--</literal> - </term> - <listitem><para>Destroy the arena. Discard all of the arena's extant - allocations using the same mechanism as for <link - linkend="arena.i.reset"><mallctl>arena.<i>.reset</mallctl></link> - (with all the same constraints and side effects), merge the arena stats - into those accessible at arena index - <constant>MALLCTL_ARENAS_DESTROYED</constant>, and then completely - discard all metadata associated with the arena. Future calls to <link - linkend="arenas.create"><mallctl>arenas.create</mallctl></link> may - recycle the arena index. Destruction will fail if any threads are - currently associated with the arena as a result of calls to <link - linkend="thread.arena"><mallctl>thread.arena</mallctl></link>.</para></listitem> - </varlistentry> - - <varlistentry id="arena.i.dss"> - <term> - <mallctl>arena.<i>.dss</mallctl> - (<type>const char *</type>) - <literal>rw</literal> - </term> - <listitem><para>Set the precedence of dss allocation as related to mmap - allocation for arena <i>, or for all arenas if <i> equals - <constant>MALLCTL_ARENAS_ALL</constant>. See <link - linkend="opt.dss"><mallctl>opt.dss</mallctl></link> for supported - settings.</para></listitem> - </varlistentry> - - <varlistentry id="arena.i.dirty_decay_ms"> - <term> - <mallctl>arena.<i>.dirty_decay_ms</mallctl> - (<type>ssize_t</type>) - <literal>rw</literal> - </term> - <listitem><para>Current per-arena approximate time in milliseconds from - the creation of a set of unused dirty pages until an equivalent set of - unused dirty pages is purged and/or reused. Each time this interface is - set, all currently unused dirty pages are considered to have fully - decayed, which causes immediate purging of all unused dirty pages unless - the decay time is set to -1 (i.e. purging disabled). See <link - linkend="opt.dirty_decay_ms"><mallctl>opt.dirty_decay_ms</mallctl></link> - for additional information.</para></listitem> - </varlistentry> - - <varlistentry id="arena.i.muzzy_decay_ms"> - <term> - <mallctl>arena.<i>.muzzy_decay_ms</mallctl> - (<type>ssize_t</type>) - <literal>rw</literal> - </term> - <listitem><para>Current per-arena approximate time in milliseconds from - the creation of a set of unused muzzy pages until an equivalent set of - unused muzzy pages is purged and/or reused. Each time this interface is - set, all currently unused muzzy pages are considered to have fully - decayed, which causes immediate purging of all unused muzzy pages unless - the decay time is set to -1 (i.e. purging disabled). See <link - linkend="opt.muzzy_decay_ms"><mallctl>opt.muzzy_decay_ms</mallctl></link> - for additional information.</para></listitem> - </varlistentry> - - <varlistentry id="arena.i.retain_grow_limit"> - <term> - <mallctl>arena.<i>.retain_grow_limit</mallctl> - (<type>size_t</type>) - <literal>rw</literal> - </term> - <listitem><para>Maximum size to grow retained region (only relevant when - <link linkend="opt.retain"><mallctl>opt.retain</mallctl></link> is - enabled). This controls the maximum increment to expand virtual memory, - or allocation through <link - linkend="arena.i.extent_hooks"><mallctl>arena.<i>extent_hooks</mallctl></link>. - In particular, if customized extent hooks reserve physical memory - (e.g. 1G huge pages), this is useful to control the allocation hook's - input size. The default is no limit.</para></listitem> - </varlistentry> - - <varlistentry id="arena.i.extent_hooks"> - <term> - <mallctl>arena.<i>.extent_hooks</mallctl> - (<type>extent_hooks_t *</type>) - <literal>rw</literal> - </term> - <listitem><para>Get or set the extent management hook functions for - arena <i>. The functions must be capable of operating on all - extant extents associated with arena <i>, usually by passing - unknown extents to the replaced functions. In practice, it is feasible - to control allocation for arenas explicitly created via <link - linkend="arenas.create"><mallctl>arenas.create</mallctl></link> such - that all extents originate from an application-supplied extent allocator - (by specifying the custom extent hook functions during arena creation). - However, the API guarantees for the automatically created arenas may be - relaxed -- hooks set there may be called in a "best effort" fashion; in - addition there may be extents created prior to the application having an - opportunity to take over extent allocation.</para> - - <programlisting language="C"><![CDATA[ -typedef extent_hooks_s extent_hooks_t; -struct extent_hooks_s { - extent_alloc_t *alloc; - extent_dalloc_t *dalloc; - extent_destroy_t *destroy; - extent_commit_t *commit; - extent_decommit_t *decommit; - extent_purge_t *purge_lazy; - extent_purge_t *purge_forced; - extent_split_t *split; - extent_merge_t *merge; -};]]></programlisting> - <para>The <type>extent_hooks_t</type> structure comprises function - pointers which are described individually below. jemalloc uses these - functions to manage extent lifetime, which starts off with allocation of - mapped committed memory, in the simplest case followed by deallocation. - However, there are performance and platform reasons to retain extents - for later reuse. Cleanup attempts cascade from deallocation to decommit - to forced purging to lazy purging, which gives the extent management - functions opportunities to reject the most permanent cleanup operations - in favor of less permanent (and often less costly) operations. All - operations except allocation can be universally opted out of by setting - the hook pointers to <constant>NULL</constant>, or selectively opted out - of by returning failure. Note that once the extent hook is set, the - structure is accessed directly by the associated arenas, so it must - remain valid for the entire lifetime of the arenas.</para> - - <funcsynopsis><funcprototype> - <funcdef>typedef void *<function>(extent_alloc_t)</function></funcdef> - <paramdef>extent_hooks_t *<parameter>extent_hooks</parameter></paramdef> - <paramdef>void *<parameter>new_addr</parameter></paramdef> - <paramdef>size_t <parameter>size</parameter></paramdef> - <paramdef>size_t <parameter>alignment</parameter></paramdef> - <paramdef>bool *<parameter>zero</parameter></paramdef> - <paramdef>bool *<parameter>commit</parameter></paramdef> - <paramdef>unsigned <parameter>arena_ind</parameter></paramdef> - </funcprototype></funcsynopsis> - <literallayout></literallayout> - <para>An extent allocation function conforms to the - <type>extent_alloc_t</type> type and upon success returns a pointer to - <parameter>size</parameter> bytes of mapped memory on behalf of arena - <parameter>arena_ind</parameter> such that the extent's base address is - a multiple of <parameter>alignment</parameter>, as well as setting - <parameter>*zero</parameter> to indicate whether the extent is zeroed - and <parameter>*commit</parameter> to indicate whether the extent is - committed. Upon error the function returns <constant>NULL</constant> - and leaves <parameter>*zero</parameter> and - <parameter>*commit</parameter> unmodified. The - <parameter>size</parameter> parameter is always a multiple of the page - size. The <parameter>alignment</parameter> parameter is always a power - of two at least as large as the page size. Zeroing is mandatory if - <parameter>*zero</parameter> is true upon function entry. Committing is - mandatory if <parameter>*commit</parameter> is true upon function entry. - If <parameter>new_addr</parameter> is not <constant>NULL</constant>, the - returned pointer must be <parameter>new_addr</parameter> on success or - <constant>NULL</constant> on error. Committed memory may be committed - in absolute terms as on a system that does not overcommit, or in - implicit terms as on a system that overcommits and satisfies physical - memory needs on demand via soft page faults. Note that replacing the - default extent allocation function makes the arena's <link - linkend="arena.i.dss"><mallctl>arena.<i>.dss</mallctl></link> - setting irrelevant.</para> - - <funcsynopsis><funcprototype> - <funcdef>typedef bool <function>(extent_dalloc_t)</function></funcdef> - <paramdef>extent_hooks_t *<parameter>extent_hooks</parameter></paramdef> - <paramdef>void *<parameter>addr</parameter></paramdef> - <paramdef>size_t <parameter>size</parameter></paramdef> - <paramdef>bool <parameter>committed</parameter></paramdef> - <paramdef>unsigned <parameter>arena_ind</parameter></paramdef> - </funcprototype></funcsynopsis> - <literallayout></literallayout> - <para> - An extent deallocation function conforms to the - <type>extent_dalloc_t</type> type and deallocates an extent at given - <parameter>addr</parameter> and <parameter>size</parameter> with - <parameter>committed</parameter>/decommited memory as indicated, on - behalf of arena <parameter>arena_ind</parameter>, returning false upon - success. If the function returns true, this indicates opt-out from - deallocation; the virtual memory mapping associated with the extent - remains mapped, in the same commit state, and available for future use, - in which case it will be automatically retained for later reuse.</para> - - <funcsynopsis><funcprototype> - <funcdef>typedef void <function>(extent_destroy_t)</function></funcdef> - <paramdef>extent_hooks_t *<parameter>extent_hooks</parameter></paramdef> - <paramdef>void *<parameter>addr</parameter></paramdef> - <paramdef>size_t <parameter>size</parameter></paramdef> - <paramdef>bool <parameter>committed</parameter></paramdef> - <paramdef>unsigned <parameter>arena_ind</parameter></paramdef> - </funcprototype></funcsynopsis> - <literallayout></literallayout> - <para> - An extent destruction function conforms to the - <type>extent_destroy_t</type> type and unconditionally destroys an - extent at given <parameter>addr</parameter> and - <parameter>size</parameter> with - <parameter>committed</parameter>/decommited memory as indicated, on - behalf of arena <parameter>arena_ind</parameter>. This function may be - called to destroy retained extents during arena destruction (see <link - linkend="arena.i.destroy"><mallctl>arena.<i>.destroy</mallctl></link>).</para> - - <funcsynopsis><funcprototype> - <funcdef>typedef bool <function>(extent_commit_t)</function></funcdef> - <paramdef>extent_hooks_t *<parameter>extent_hooks</parameter></paramdef> - <paramdef>void *<parameter>addr</parameter></paramdef> - <paramdef>size_t <parameter>size</parameter></paramdef> - <paramdef>size_t <parameter>offset</parameter></paramdef> - <paramdef>size_t <parameter>length</parameter></paramdef> - <paramdef>unsigned <parameter>arena_ind</parameter></paramdef> - </funcprototype></funcsynopsis> - <literallayout></literallayout> - <para>An extent commit function conforms to the - <type>extent_commit_t</type> type and commits zeroed physical memory to - back pages within an extent at given <parameter>addr</parameter> and - <parameter>size</parameter> at <parameter>offset</parameter> bytes, - extending for <parameter>length</parameter> on behalf of arena - <parameter>arena_ind</parameter>, returning false upon success. - Committed memory may be committed in absolute terms as on a system that - does not overcommit, or in implicit terms as on a system that - overcommits and satisfies physical memory needs on demand via soft page - faults. If the function returns true, this indicates insufficient - physical memory to satisfy the request.</para> - - <funcsynopsis><funcprototype> - <funcdef>typedef bool <function>(extent_decommit_t)</function></funcdef> - <paramdef>extent_hooks_t *<parameter>extent_hooks</parameter></paramdef> - <paramdef>void *<parameter>addr</parameter></paramdef> - <paramdef>size_t <parameter>size</parameter></paramdef> - <paramdef>size_t <parameter>offset</parameter></paramdef> - <paramdef>size_t <parameter>length</parameter></paramdef> - <paramdef>unsigned <parameter>arena_ind</parameter></paramdef> - </funcprototype></funcsynopsis> - <literallayout></literallayout> - <para>An extent decommit function conforms to the - <type>extent_decommit_t</type> type and decommits any physical memory - that is backing pages within an extent at given - <parameter>addr</parameter> and <parameter>size</parameter> at - <parameter>offset</parameter> bytes, extending for - <parameter>length</parameter> on behalf of arena - <parameter>arena_ind</parameter>, returning false upon success, in which - case the pages will be committed via the extent commit function before - being reused. If the function returns true, this indicates opt-out from - decommit; the memory remains committed and available for future use, in - which case it will be automatically retained for later reuse.</para> - - <funcsynopsis><funcprototype> - <funcdef>typedef bool <function>(extent_purge_t)</function></funcdef> - <paramdef>extent_hooks_t *<parameter>extent_hooks</parameter></paramdef> - <paramdef>void *<parameter>addr</parameter></paramdef> - <paramdef>size_t <parameter>size</parameter></paramdef> - <paramdef>size_t <parameter>offset</parameter></paramdef> - <paramdef>size_t <parameter>length</parameter></paramdef> - <paramdef>unsigned <parameter>arena_ind</parameter></paramdef> - </funcprototype></funcsynopsis> - <literallayout></literallayout> - <para>An extent purge function conforms to the - <type>extent_purge_t</type> type and discards physical pages - within the virtual memory mapping associated with an extent at given - <parameter>addr</parameter> and <parameter>size</parameter> at - <parameter>offset</parameter> bytes, extending for - <parameter>length</parameter> on behalf of arena - <parameter>arena_ind</parameter>. A lazy extent purge function (e.g. - implemented via - <function>madvise(<parameter>...</parameter><parameter><constant>MADV_FREE</constant></parameter>)</function>) - can delay purging indefinitely and leave the pages within the purged - virtual memory range in an indeterminite state, whereas a forced extent - purge function immediately purges, and the pages within the virtual - memory range will be zero-filled the next time they are accessed. If - the function returns true, this indicates failure to purge.</para> - - <funcsynopsis><funcprototype> - <funcdef>typedef bool <function>(extent_split_t)</function></funcdef> - <paramdef>extent_hooks_t *<parameter>extent_hooks</parameter></paramdef> - <paramdef>void *<parameter>addr</parameter></paramdef> - <paramdef>size_t <parameter>size</parameter></paramdef> - <paramdef>size_t <parameter>size_a</parameter></paramdef> - <paramdef>size_t <parameter>size_b</parameter></paramdef> - <paramdef>bool <parameter>committed</parameter></paramdef> - <paramdef>unsigned <parameter>arena_ind</parameter></paramdef> - </funcprototype></funcsynopsis> - <literallayout></literallayout> - <para>An extent split function conforms to the - <type>extent_split_t</type> type and optionally splits an extent at - given <parameter>addr</parameter> and <parameter>size</parameter> into - two adjacent extents, the first of <parameter>size_a</parameter> bytes, - and the second of <parameter>size_b</parameter> bytes, operating on - <parameter>committed</parameter>/decommitted memory as indicated, on - behalf of arena <parameter>arena_ind</parameter>, returning false upon - success. If the function returns true, this indicates that the extent - remains unsplit and therefore should continue to be operated on as a - whole.</para> - - <funcsynopsis><funcprototype> - <funcdef>typedef bool <function>(extent_merge_t)</function></funcdef> - <paramdef>extent_hooks_t *<parameter>extent_hooks</parameter></paramdef> - <paramdef>void *<parameter>addr_a</parameter></paramdef> - <paramdef>size_t <parameter>size_a</parameter></paramdef> - <paramdef>void *<parameter>addr_b</parameter></paramdef> - <paramdef>size_t <parameter>size_b</parameter></paramdef> - <paramdef>bool <parameter>committed</parameter></paramdef> - <paramdef>unsigned <parameter>arena_ind</parameter></paramdef> - </funcprototype></funcsynopsis> - <literallayout></literallayout> - <para>An extent merge function conforms to the - <type>extent_merge_t</type> type and optionally merges adjacent extents, - at given <parameter>addr_a</parameter> and <parameter>size_a</parameter> - with given <parameter>addr_b</parameter> and - <parameter>size_b</parameter> into one contiguous extent, operating on - <parameter>committed</parameter>/decommitted memory as indicated, on - behalf of arena <parameter>arena_ind</parameter>, returning false upon - success. If the function returns true, this indicates that the extents - remain distinct mappings and therefore should continue to be operated on - independently.</para> - </listitem> - </varlistentry> - - <varlistentry id="arenas.narenas"> - <term> - <mallctl>arenas.narenas</mallctl> - (<type>unsigned</type>) - <literal>r-</literal> - </term> - <listitem><para>Current limit on number of arenas.</para></listitem> - </varlistentry> - - <varlistentry id="arenas.dirty_decay_ms"> - <term> - <mallctl>arenas.dirty_decay_ms</mallctl> - (<type>ssize_t</type>) - <literal>rw</literal> - </term> - <listitem><para>Current default per-arena approximate time in - milliseconds from the creation of a set of unused dirty pages until an - equivalent set of unused dirty pages is purged and/or reused, used to - initialize <link - linkend="arena.i.dirty_decay_ms"><mallctl>arena.<i>.dirty_decay_ms</mallctl></link> - during arena creation. See <link - linkend="opt.dirty_decay_ms"><mallctl>opt.dirty_decay_ms</mallctl></link> - for additional information.</para></listitem> - </varlistentry> - - <varlistentry id="arenas.muzzy_decay_ms"> - <term> - <mallctl>arenas.muzzy_decay_ms</mallctl> - (<type>ssize_t</type>) - <literal>rw</literal> - </term> - <listitem><para>Current default per-arena approximate time in - milliseconds from the creation of a set of unused muzzy pages until an - equivalent set of unused muzzy pages is purged and/or reused, used to - initialize <link - linkend="arena.i.muzzy_decay_ms"><mallctl>arena.<i>.muzzy_decay_ms</mallctl></link> - during arena creation. See <link - linkend="opt.muzzy_decay_ms"><mallctl>opt.muzzy_decay_ms</mallctl></link> - for additional information.</para></listitem> - </varlistentry> - - <varlistentry id="arenas.quantum"> - <term> - <mallctl>arenas.quantum</mallctl> - (<type>size_t</type>) - <literal>r-</literal> - </term> - <listitem><para>Quantum size.</para></listitem> - </varlistentry> - - <varlistentry id="arenas.page"> - <term> - <mallctl>arenas.page</mallctl> - (<type>size_t</type>) - <literal>r-</literal> - </term> - <listitem><para>Page size.</para></listitem> - </varlistentry> - - <varlistentry id="arenas.tcache_max"> - <term> - <mallctl>arenas.tcache_max</mallctl> - (<type>size_t</type>) - <literal>r-</literal> - </term> - <listitem><para>Maximum thread-cached size class.</para></listitem> - </varlistentry> - - <varlistentry id="arenas.nbins"> - <term> - <mallctl>arenas.nbins</mallctl> - (<type>unsigned</type>) - <literal>r-</literal> - </term> - <listitem><para>Number of bin size classes.</para></listitem> - </varlistentry> - - <varlistentry id="arenas.nhbins"> - <term> - <mallctl>arenas.nhbins</mallctl> - (<type>unsigned</type>) - <literal>r-</literal> - </term> - <listitem><para>Total number of thread cache bin size - classes.</para></listitem> - </varlistentry> - - <varlistentry id="arenas.bin.i.size"> - <term> - <mallctl>arenas.bin.<i>.size</mallctl> - (<type>size_t</type>) - <literal>r-</literal> - </term> - <listitem><para>Maximum size supported by size class.</para></listitem> - </varlistentry> - - <varlistentry id="arenas.bin.i.nregs"> - <term> - <mallctl>arenas.bin.<i>.nregs</mallctl> - (<type>uint32_t</type>) - <literal>r-</literal> - </term> - <listitem><para>Number of regions per slab.</para></listitem> - </varlistentry> - - <varlistentry id="arenas.bin.i.slab_size"> - <term> - <mallctl>arenas.bin.<i>.slab_size</mallctl> - (<type>size_t</type>) - <literal>r-</literal> - </term> - <listitem><para>Number of bytes per slab.</para></listitem> - </varlistentry> - - <varlistentry id="arenas.nlextents"> - <term> - <mallctl>arenas.nlextents</mallctl> - (<type>unsigned</type>) - <literal>r-</literal> - </term> - <listitem><para>Total number of large size classes.</para></listitem> - </varlistentry> - - <varlistentry id="arenas.lextent.i.size"> - <term> - <mallctl>arenas.lextent.<i>.size</mallctl> - (<type>size_t</type>) - <literal>r-</literal> - </term> - <listitem><para>Maximum size supported by this large size - class.</para></listitem> - </varlistentry> - - <varlistentry id="arenas.create"> - <term> - <mallctl>arenas.create</mallctl> - (<type>unsigned</type>, <type>extent_hooks_t *</type>) - <literal>rw</literal> - </term> - <listitem><para>Explicitly create a new arena outside the range of - automatically managed arenas, with optionally specified extent hooks, - and return the new arena index.</para></listitem> - </varlistentry> - - <varlistentry id="arenas.lookup"> - <term> - <mallctl>arenas.lookup</mallctl> - (<type>unsigned</type>, <type>void*</type>) - <literal>rw</literal> - </term> - <listitem><para>Index of the arena to which an allocation belongs to.</para></listitem> - </varlistentry> - - <varlistentry id="prof.thread_active_init"> - <term> - <mallctl>prof.thread_active_init</mallctl> - (<type>bool</type>) - <literal>rw</literal> - [<option>--enable-prof</option>] - </term> - <listitem><para>Control the initial setting for <link - linkend="thread.prof.active"><mallctl>thread.prof.active</mallctl></link> - in newly created threads. See the <link - linkend="opt.prof_thread_active_init"><mallctl>opt.prof_thread_active_init</mallctl></link> - option for additional information.</para></listitem> - </varlistentry> - - <varlistentry id="prof.active"> - <term> - <mallctl>prof.active</mallctl> - (<type>bool</type>) - <literal>rw</literal> - [<option>--enable-prof</option>] - </term> - <listitem><para>Control whether sampling is currently active. See the - <link - linkend="opt.prof_active"><mallctl>opt.prof_active</mallctl></link> - option for additional information, as well as the interrelated <link - linkend="thread.prof.active"><mallctl>thread.prof.active</mallctl></link> - mallctl.</para></listitem> - </varlistentry> - - <varlistentry id="prof.dump"> - <term> - <mallctl>prof.dump</mallctl> - (<type>const char *</type>) - <literal>-w</literal> - [<option>--enable-prof</option>] - </term> - <listitem><para>Dump a memory profile to the specified file, or if NULL - is specified, to a file according to the pattern - <filename><prefix>.<pid>.<seq>.m<mseq>.heap</filename>, - where <literal><prefix></literal> is controlled by the - <link - linkend="opt.prof_prefix"><mallctl>opt.prof_prefix</mallctl></link> - option.</para></listitem> - </varlistentry> - - <varlistentry id="prof.gdump"> - <term> - <mallctl>prof.gdump</mallctl> - (<type>bool</type>) - <literal>rw</literal> - [<option>--enable-prof</option>] - </term> - <listitem><para>When enabled, trigger a memory profile dump every time - the total virtual memory exceeds the previous maximum. Profiles are - dumped to files named according to the pattern - <filename><prefix>.<pid>.<seq>.u<useq>.heap</filename>, - where <literal><prefix></literal> is controlled by the <link - linkend="opt.prof_prefix"><mallctl>opt.prof_prefix</mallctl></link> - option.</para></listitem> - </varlistentry> - - <varlistentry id="prof.reset"> - <term> - <mallctl>prof.reset</mallctl> - (<type>size_t</type>) - <literal>-w</literal> - [<option>--enable-prof</option>] - </term> - <listitem><para>Reset all memory profile statistics, and optionally - update the sample rate (see <link - linkend="opt.lg_prof_sample"><mallctl>opt.lg_prof_sample</mallctl></link> - and <link - linkend="prof.lg_sample"><mallctl>prof.lg_sample</mallctl></link>). - </para></listitem> - </varlistentry> - - <varlistentry id="prof.lg_sample"> - <term> - <mallctl>prof.lg_sample</mallctl> - (<type>size_t</type>) - <literal>r-</literal> - [<option>--enable-prof</option>] - </term> - <listitem><para>Get the current sample rate (see <link - linkend="opt.lg_prof_sample"><mallctl>opt.lg_prof_sample</mallctl></link>). - </para></listitem> - </varlistentry> - - <varlistentry id="prof.interval"> - <term> - <mallctl>prof.interval</mallctl> - (<type>uint64_t</type>) - <literal>r-</literal> - [<option>--enable-prof</option>] - </term> - <listitem><para>Average number of bytes allocated between - interval-based profile dumps. See the - <link - linkend="opt.lg_prof_interval"><mallctl>opt.lg_prof_interval</mallctl></link> - option for additional information.</para></listitem> - </varlistentry> - - <varlistentry id="stats.allocated"> - <term> - <mallctl>stats.allocated</mallctl> - (<type>size_t</type>) - <literal>r-</literal> - [<option>--enable-stats</option>] - </term> - <listitem><para>Total number of bytes allocated by the - application.</para></listitem> - </varlistentry> - - <varlistentry id="stats.active"> - <term> - <mallctl>stats.active</mallctl> - (<type>size_t</type>) - <literal>r-</literal> - [<option>--enable-stats</option>] - </term> - <listitem><para>Total number of bytes in active pages allocated by the - application. This is a multiple of the page size, and greater than or - equal to <link - linkend="stats.allocated"><mallctl>stats.allocated</mallctl></link>. - This does not include <link linkend="stats.arenas.i.pdirty"> - <mallctl>stats.arenas.<i>.pdirty</mallctl></link>, - <link linkend="stats.arenas.i.pmuzzy"> - <mallctl>stats.arenas.<i>.pmuzzy</mallctl></link>, nor pages - entirely devoted to allocator metadata.</para></listitem> - </varlistentry> - - <varlistentry id="stats.metadata"> - <term> - <mallctl>stats.metadata</mallctl> - (<type>size_t</type>) - <literal>r-</literal> - [<option>--enable-stats</option>] - </term> - <listitem><para>Total number of bytes dedicated to metadata, which - comprise base allocations used for bootstrap-sensitive allocator - metadata structures (see <link - linkend="stats.arenas.i.base"><mallctl>stats.arenas.<i>.base</mallctl></link>) - and internal allocations (see <link - linkend="stats.arenas.i.internal"><mallctl>stats.arenas.<i>.internal</mallctl></link>). - Transparent huge page (enabled with <link - linkend="opt.metadata_thp">opt.metadata_thp</link>) usage is not - considered.</para></listitem> - </varlistentry> - - <varlistentry id="stats.metadata_thp"> - <term> - <mallctl>stats.metadata_thp</mallctl> - (<type>size_t</type>) - <literal>r-</literal> - [<option>--enable-stats</option>] - </term> - <listitem><para>Number of transparent huge pages (THP) used for - metadata. See <link - linkend="stats.metadata"><mallctl>stats.metadata</mallctl></link> and - <link linkend="opt.metadata_thp">opt.metadata_thp</link>) for - details.</para></listitem> - </varlistentry> - - <varlistentry id="stats.resident"> - <term> - <mallctl>stats.resident</mallctl> - (<type>size_t</type>) - <literal>r-</literal> - [<option>--enable-stats</option>] - </term> - <listitem><para>Maximum number of bytes in physically resident data - pages mapped by the allocator, comprising all pages dedicated to - allocator metadata, pages backing active allocations, and unused dirty - pages. This is a maximum rather than precise because pages may not - actually be physically resident if they correspond to demand-zeroed - virtual memory that has not yet been touched. This is a multiple of the - page size, and is larger than <link - linkend="stats.active"><mallctl>stats.active</mallctl></link>.</para></listitem> - </varlistentry> - - <varlistentry id="stats.mapped"> - <term> - <mallctl>stats.mapped</mallctl> - (<type>size_t</type>) - <literal>r-</literal> - [<option>--enable-stats</option>] - </term> - <listitem><para>Total number of bytes in active extents mapped by the - allocator. This is larger than <link - linkend="stats.active"><mallctl>stats.active</mallctl></link>. This - does not include inactive extents, even those that contain unused dirty - pages, which means that there is no strict ordering between this and - <link - linkend="stats.resident"><mallctl>stats.resident</mallctl></link>.</para></listitem> - </varlistentry> - - <varlistentry id="stats.retained"> - <term> - <mallctl>stats.retained</mallctl> - (<type>size_t</type>) - <literal>r-</literal> - [<option>--enable-stats</option>] - </term> - <listitem><para>Total number of bytes in virtual memory mappings that - were retained rather than being returned to the operating system via - e.g. <citerefentry><refentrytitle>munmap</refentrytitle> - <manvolnum>2</manvolnum></citerefentry> or similar. Retained virtual - memory is typically untouched, decommitted, or purged, so it has no - strongly associated physical memory (see <link - linkend="arena.i.extent_hooks">extent hooks</link> for details). - Retained memory is excluded from mapped memory statistics, e.g. <link - linkend="stats.mapped"><mallctl>stats.mapped</mallctl></link>. - </para></listitem> - </varlistentry> - - <varlistentry id="stats.background_thread.num_threads"> - <term> - <mallctl>stats.background_thread.num_threads</mallctl> - (<type>size_t</type>) - <literal>r-</literal> - [<option>--enable-stats</option>] - </term> - <listitem><para> Number of <link linkend="background_thread">background - threads</link> running currently.</para></listitem> - </varlistentry> - - <varlistentry id="stats.background_thread.num_runs"> - <term> - <mallctl>stats.background_thread.num_runs</mallctl> - (<type>uint64_t</type>) - <literal>r-</literal> - [<option>--enable-stats</option>] - </term> - <listitem><para> Total number of runs from all <link - linkend="background_thread">background threads</link>.</para></listitem> - </varlistentry> - - <varlistentry id="stats.background_thread.run_interval"> - <term> - <mallctl>stats.background_thread.run_interval</mallctl> - (<type>uint64_t</type>) - <literal>r-</literal> - [<option>--enable-stats</option>] - </term> - <listitem><para> Average run interval in nanoseconds of <link - linkend="background_thread">background threads</link>.</para></listitem> - </varlistentry> - - <varlistentry id="stats.mutexes.ctl"> - <term> - <mallctl>stats.mutexes.ctl.{counter};</mallctl> - (<type>counter specific type</type>) - <literal>r-</literal> - [<option>--enable-stats</option>] - </term> - <listitem><para>Statistics on <varname>ctl</varname> mutex (global - scope; mallctl related). <mallctl>{counter}</mallctl> is one of the - counters below:</para> - <varlistentry id="mutex_counters"> - <listitem><para><varname>num_ops</varname> (<type>uint64_t</type>): - Total number of lock acquisition operations on this mutex.</para> - - <para><varname>num_spin_acq</varname> (<type>uint64_t</type>): Number - of times the mutex was spin-acquired. When the mutex is currently - locked and cannot be acquired immediately, a short period of - spin-retry within jemalloc will be performed. Acquired through spin - generally means the contention was lightweight and not causing context - switches.</para> - - <para><varname>num_wait</varname> (<type>uint64_t</type>): Number of - times the mutex was wait-acquired, which means the mutex contention - was not solved by spin-retry, and blocking operation was likely - involved in order to acquire the mutex. This event generally implies - higher cost / longer delay, and should be investigated if it happens - often.</para> - - <para><varname>max_wait_time</varname> (<type>uint64_t</type>): - Maximum length of time in nanoseconds spent on a single wait-acquired - lock operation. Note that to avoid profiling overhead on the common - path, this does not consider spin-acquired cases.</para> - - <para><varname>total_wait_time</varname> (<type>uint64_t</type>): - Cumulative time in nanoseconds spent on wait-acquired lock operations. - Similarly, spin-acquired cases are not considered.</para> - - <para><varname>max_num_thds</varname> (<type>uint32_t</type>): Maximum - number of threads waiting on this mutex simultaneously. Similarly, - spin-acquired cases are not considered.</para> - - <para><varname>num_owner_switch</varname> (<type>uint64_t</type>): - Number of times the current mutex owner is different from the previous - one. This event does not generally imply an issue; rather it is an - indicator of how often the protected data are accessed by different - threads. - </para> - </listitem> - </varlistentry> - </listitem> - </varlistentry> - - <varlistentry id="stats.mutexes.background_thread"> - <term> - <mallctl>stats.mutexes.background_thread.{counter}</mallctl> - (<type>counter specific type</type>) <literal>r-</literal> - [<option>--enable-stats</option>] - </term> - <listitem><para>Statistics on <varname>background_thread</varname> mutex - (global scope; <link - linkend="background_thread"><mallctl>background_thread</mallctl></link> - related). <mallctl>{counter}</mallctl> is one of the counters in <link - linkend="mutex_counters">mutex profiling - counters</link>.</para></listitem> - </varlistentry> - - <varlistentry id="stats.mutexes.prof"> - <term> - <mallctl>stats.mutexes.prof.{counter}</mallctl> - (<type>counter specific type</type>) <literal>r-</literal> - [<option>--enable-stats</option>] - </term> - <listitem><para>Statistics on <varname>prof</varname> mutex (global - scope; profiling related). <mallctl>{counter}</mallctl> is one of the - counters in <link linkend="mutex_counters">mutex profiling - counters</link>.</para></listitem> - </varlistentry> - - <varlistentry id="stats.mutexes.reset"> - <term> - <mallctl>stats.mutexes.reset</mallctl> - (<type>void</type>) <literal>--</literal> - [<option>--enable-stats</option>] - </term> - <listitem><para>Reset all mutex profile statistics, including global - mutexes, arena mutexes and bin mutexes.</para></listitem> - </varlistentry> - - <varlistentry id="stats.arenas.i.dss"> - <term> - <mallctl>stats.arenas.<i>.dss</mallctl> - (<type>const char *</type>) - <literal>r-</literal> - </term> - <listitem><para>dss (<citerefentry><refentrytitle>sbrk</refentrytitle> - <manvolnum>2</manvolnum></citerefentry>) allocation precedence as - related to <citerefentry><refentrytitle>mmap</refentrytitle> - <manvolnum>2</manvolnum></citerefentry> allocation. See <link - linkend="opt.dss"><mallctl>opt.dss</mallctl></link> for details. - </para></listitem> - </varlistentry> - - <varlistentry id="stats.arenas.i.dirty_decay_ms"> - <term> - <mallctl>stats.arenas.<i>.dirty_decay_ms</mallctl> - (<type>ssize_t</type>) - <literal>r-</literal> - </term> - <listitem><para>Approximate time in milliseconds from the creation of a - set of unused dirty pages until an equivalent set of unused dirty pages - is purged and/or reused. See <link - linkend="opt.dirty_decay_ms"><mallctl>opt.dirty_decay_ms</mallctl></link> - for details.</para></listitem> - </varlistentry> - - <varlistentry id="stats.arenas.i.muzzy_decay_ms"> - <term> - <mallctl>stats.arenas.<i>.muzzy_decay_ms</mallctl> - (<type>ssize_t</type>) - <literal>r-</literal> - </term> - <listitem><para>Approximate time in milliseconds from the creation of a - set of unused muzzy pages until an equivalent set of unused muzzy pages - is purged and/or reused. See <link - linkend="opt.muzzy_decay_ms"><mallctl>opt.muzzy_decay_ms</mallctl></link> - for details.</para></listitem> - </varlistentry> - - <varlistentry id="stats.arenas.i.nthreads"> - <term> - <mallctl>stats.arenas.<i>.nthreads</mallctl> - (<type>unsigned</type>) - <literal>r-</literal> - </term> - <listitem><para>Number of threads currently assigned to - arena.</para></listitem> - </varlistentry> - - <varlistentry id="stats.arenas.i.uptime"> - <term> - <mallctl>stats.arenas.<i>.uptime</mallctl> - (<type>uint64_t</type>) - <literal>r-</literal> - </term> - <listitem><para>Time elapsed (in nanoseconds) since the arena was - created. If <i> equals <constant>0</constant> or - <constant>MALLCTL_ARENAS_ALL</constant>, this is the uptime since malloc - initialization.</para></listitem> - </varlistentry> - - <varlistentry id="stats.arenas.i.pactive"> - <term> - <mallctl>stats.arenas.<i>.pactive</mallctl> - (<type>size_t</type>) - <literal>r-</literal> - </term> - <listitem><para>Number of pages in active extents.</para></listitem> - </varlistentry> - - <varlistentry id="stats.arenas.i.pdirty"> - <term> - <mallctl>stats.arenas.<i>.pdirty</mallctl> - (<type>size_t</type>) - <literal>r-</literal> - </term> - <listitem><para>Number of pages within unused extents that are - potentially dirty, and for which <function>madvise()</function> or - similar has not been called. See <link - linkend="opt.dirty_decay_ms"><mallctl>opt.dirty_decay_ms</mallctl></link> - for a description of dirty pages.</para></listitem> - </varlistentry> - - <varlistentry id="stats.arenas.i.pmuzzy"> - <term> - <mallctl>stats.arenas.<i>.pmuzzy</mallctl> - (<type>size_t</type>) - <literal>r-</literal> - </term> - <listitem><para>Number of pages within unused extents that are muzzy. - See <link - linkend="opt.muzzy_decay_ms"><mallctl>opt.muzzy_decay_ms</mallctl></link> - for a description of muzzy pages.</para></listitem> - </varlistentry> - - <varlistentry id="stats.arenas.i.mapped"> - <term> - <mallctl>stats.arenas.<i>.mapped</mallctl> - (<type>size_t</type>) - <literal>r-</literal> - [<option>--enable-stats</option>] - </term> - <listitem><para>Number of mapped bytes.</para></listitem> - </varlistentry> - - <varlistentry id="stats.arenas.i.retained"> - <term> - <mallctl>stats.arenas.<i>.retained</mallctl> - (<type>size_t</type>) - <literal>r-</literal> - [<option>--enable-stats</option>] - </term> - <listitem><para>Number of retained bytes. See <link - linkend="stats.retained"><mallctl>stats.retained</mallctl></link> for - details.</para></listitem> - </varlistentry> - - <varlistentry id="stats.arenas.i.extent_avail"> - <term> - <mallctl>stats.arenas.<i>.extent_avail</mallctl> - (<type>size_t</type>) - <literal>r-</literal> - [<option>--enable-stats</option>] - </term> - <listitem><para>Number of allocated (but unused) extent structs in this - arena.</para></listitem> - </varlistentry> - - <varlistentry id="stats.arenas.i.base"> - <term> - <mallctl>stats.arenas.<i>.base</mallctl> - (<type>size_t</type>) - <literal>r-</literal> - [<option>--enable-stats</option>] - </term> - <listitem><para> - Number of bytes dedicated to bootstrap-sensitive allocator metadata - structures.</para></listitem> - </varlistentry> - - <varlistentry id="stats.arenas.i.internal"> - <term> - <mallctl>stats.arenas.<i>.internal</mallctl> - (<type>size_t</type>) - <literal>r-</literal> - [<option>--enable-stats</option>] - </term> - <listitem><para>Number of bytes dedicated to internal allocations. - Internal allocations differ from application-originated allocations in - that they are for internal use, and that they are omitted from heap - profiles.</para></listitem> - </varlistentry> - - <varlistentry id="stats.arenas.i.metadata_thp"> - <term> - <mallctl>stats.arenas.<i>.metadata_thp</mallctl> - (<type>size_t</type>) - <literal>r-</literal> - [<option>--enable-stats</option>] - </term> - <listitem><para>Number of transparent huge pages (THP) used for - metadata. See <link linkend="opt.metadata_thp">opt.metadata_thp</link> - for details.</para></listitem> - </varlistentry> - - <varlistentry id="stats.arenas.i.resident"> - <term> - <mallctl>stats.arenas.<i>.resident</mallctl> - (<type>size_t</type>) - <literal>r-</literal> - [<option>--enable-stats</option>] - </term> - <listitem><para>Maximum number of bytes in physically resident data - pages mapped by the arena, comprising all pages dedicated to allocator - metadata, pages backing active allocations, and unused dirty pages. - This is a maximum rather than precise because pages may not actually be - physically resident if they correspond to demand-zeroed virtual memory - that has not yet been touched. This is a multiple of the page - size.</para></listitem> - </varlistentry> - - <varlistentry id="stats.arenas.i.dirty_npurge"> - <term> - <mallctl>stats.arenas.<i>.dirty_npurge</mallctl> - (<type>uint64_t</type>) - <literal>r-</literal> - [<option>--enable-stats</option>] - </term> - <listitem><para>Number of dirty page purge sweeps performed. - </para></listitem> - </varlistentry> - - <varlistentry id="stats.arenas.i.dirty_nmadvise"> - <term> - <mallctl>stats.arenas.<i>.dirty_nmadvise</mallctl> - (<type>uint64_t</type>) - <literal>r-</literal> - [<option>--enable-stats</option>] - </term> - <listitem><para>Number of <function>madvise()</function> or similar - calls made to purge dirty pages.</para></listitem> - </varlistentry> - - <varlistentry id="stats.arenas.i.dirty_purged"> - <term> - <mallctl>stats.arenas.<i>.dirty_purged</mallctl> - (<type>uint64_t</type>) - <literal>r-</literal> - [<option>--enable-stats</option>] - </term> - <listitem><para>Number of dirty pages purged.</para></listitem> - </varlistentry> - - <varlistentry id="stats.arenas.i.muzzy_npurge"> - <term> - <mallctl>stats.arenas.<i>.muzzy_npurge</mallctl> - (<type>uint64_t</type>) - <literal>r-</literal> - [<option>--enable-stats</option>] - </term> - <listitem><para>Number of muzzy page purge sweeps performed. - </para></listitem> - </varlistentry> - - <varlistentry id="stats.arenas.i.muzzy_nmadvise"> - <term> - <mallctl>stats.arenas.<i>.muzzy_nmadvise</mallctl> - (<type>uint64_t</type>) - <literal>r-</literal> - [<option>--enable-stats</option>] - </term> - <listitem><para>Number of <function>madvise()</function> or similar - calls made to purge muzzy pages.</para></listitem> - </varlistentry> - - <varlistentry id="stats.arenas.i.muzzy_purged"> - <term> - <mallctl>stats.arenas.<i>.muzzy_purged</mallctl> - (<type>uint64_t</type>) - <literal>r-</literal> - [<option>--enable-stats</option>] - </term> - <listitem><para>Number of muzzy pages purged.</para></listitem> - </varlistentry> - - <varlistentry id="stats.arenas.i.small.allocated"> - <term> - <mallctl>stats.arenas.<i>.small.allocated</mallctl> - (<type>size_t</type>) - <literal>r-</literal> - [<option>--enable-stats</option>] - </term> - <listitem><para>Number of bytes currently allocated by small objects. - </para></listitem> - </varlistentry> - - <varlistentry id="stats.arenas.i.small.nmalloc"> - <term> - <mallctl>stats.arenas.<i>.small.nmalloc</mallctl> - (<type>uint64_t</type>) - <literal>r-</literal> - [<option>--enable-stats</option>] - </term> - <listitem><para>Cumulative number of times a small allocation was - requested from the arena's bins, whether to fill the relevant tcache if - <link linkend="opt.tcache"><mallctl>opt.tcache</mallctl></link> is - enabled, or to directly satisfy an allocation request - otherwise.</para></listitem> - </varlistentry> - - <varlistentry id="stats.arenas.i.small.ndalloc"> - <term> - <mallctl>stats.arenas.<i>.small.ndalloc</mallctl> - (<type>uint64_t</type>) - <literal>r-</literal> - [<option>--enable-stats</option>] - </term> - <listitem><para>Cumulative number of times a small allocation was - returned to the arena's bins, whether to flush the relevant tcache if - <link linkend="opt.tcache"><mallctl>opt.tcache</mallctl></link> is - enabled, or to directly deallocate an allocation - otherwise.</para></listitem> - </varlistentry> - - <varlistentry id="stats.arenas.i.small.nrequests"> - <term> - <mallctl>stats.arenas.<i>.small.nrequests</mallctl> - (<type>uint64_t</type>) - <literal>r-</literal> - [<option>--enable-stats</option>] - </term> - <listitem><para>Cumulative number of allocation requests satisfied by - all bin size classes.</para></listitem> - </varlistentry> - - <varlistentry id="stats.arenas.i.small.nfills"> - <term> - <mallctl>stats.arenas.<i>.small.nfills</mallctl> - (<type>uint64_t</type>) - <literal>r-</literal> - [<option>--enable-stats</option>] - </term> - <listitem><para>Cumulative number of tcache fills by all small size - classes.</para></listitem> - </varlistentry> - - <varlistentry id="stats.arenas.i.small.nflushes"> - <term> - <mallctl>stats.arenas.<i>.small.nflushes</mallctl> - (<type>uint64_t</type>) - <literal>r-</literal> - [<option>--enable-stats</option>] - </term> - <listitem><para>Cumulative number of tcache flushes by all small size - classes.</para></listitem> - </varlistentry> - - <varlistentry id="stats.arenas.i.large.allocated"> - <term> - <mallctl>stats.arenas.<i>.large.allocated</mallctl> - (<type>size_t</type>) - <literal>r-</literal> - [<option>--enable-stats</option>] - </term> - <listitem><para>Number of bytes currently allocated by large objects. - </para></listitem> - </varlistentry> - - <varlistentry id="stats.arenas.i.large.nmalloc"> - <term> - <mallctl>stats.arenas.<i>.large.nmalloc</mallctl> - (<type>uint64_t</type>) - <literal>r-</literal> - [<option>--enable-stats</option>] - </term> - <listitem><para>Cumulative number of times a large extent was allocated - from the arena, whether to fill the relevant tcache if <link - linkend="opt.tcache"><mallctl>opt.tcache</mallctl></link> is enabled and - the size class is within the range being cached, or to directly satisfy - an allocation request otherwise.</para></listitem> - </varlistentry> - - <varlistentry id="stats.arenas.i.large.ndalloc"> - <term> - <mallctl>stats.arenas.<i>.large.ndalloc</mallctl> - (<type>uint64_t</type>) - <literal>r-</literal> - [<option>--enable-stats</option>] - </term> - <listitem><para>Cumulative number of times a large extent was returned - to the arena, whether to flush the relevant tcache if <link - linkend="opt.tcache"><mallctl>opt.tcache</mallctl></link> is enabled and - the size class is within the range being cached, or to directly - deallocate an allocation otherwise.</para></listitem> - </varlistentry> - - <varlistentry id="stats.arenas.i.large.nrequests"> - <term> - <mallctl>stats.arenas.<i>.large.nrequests</mallctl> - (<type>uint64_t</type>) - <literal>r-</literal> - [<option>--enable-stats</option>] - </term> - <listitem><para>Cumulative number of allocation requests satisfied by - all large size classes.</para></listitem> - </varlistentry> - - <varlistentry id="stats.arenas.i.large.nfills"> - <term> - <mallctl>stats.arenas.<i>.large.nfills</mallctl> - (<type>uint64_t</type>) - <literal>r-</literal> - [<option>--enable-stats</option>] - </term> - <listitem><para>Cumulative number of tcache fills by all large size - classes.</para></listitem> - </varlistentry> - - <varlistentry id="stats.arenas.i.large.nflushes"> - <term> - <mallctl>stats.arenas.<i>.large.nflushes</mallctl> - (<type>uint64_t</type>) - <literal>r-</literal> - [<option>--enable-stats</option>] - </term> - <listitem><para>Cumulative number of tcache flushes by all large size - classes.</para></listitem> - </varlistentry> - - <varlistentry id="stats.arenas.i.bins.j.nmalloc"> - <term> - <mallctl>stats.arenas.<i>.bins.<j>.nmalloc</mallctl> - (<type>uint64_t</type>) - <literal>r-</literal> - [<option>--enable-stats</option>] - </term> - <listitem><para>Cumulative number of times a bin region of the - corresponding size class was allocated from the arena, whether to fill - the relevant tcache if <link - linkend="opt.tcache"><mallctl>opt.tcache</mallctl></link> is enabled, or - to directly satisfy an allocation request otherwise.</para></listitem> - </varlistentry> - - <varlistentry id="stats.arenas.i.bins.j.ndalloc"> - <term> - <mallctl>stats.arenas.<i>.bins.<j>.ndalloc</mallctl> - (<type>uint64_t</type>) - <literal>r-</literal> - [<option>--enable-stats</option>] - </term> - <listitem><para>Cumulative number of times a bin region of the - corresponding size class was returned to the arena, whether to flush the - relevant tcache if <link - linkend="opt.tcache"><mallctl>opt.tcache</mallctl></link> is enabled, or - to directly deallocate an allocation otherwise.</para></listitem> - </varlistentry> - - <varlistentry id="stats.arenas.i.bins.j.nrequests"> - <term> - <mallctl>stats.arenas.<i>.bins.<j>.nrequests</mallctl> - (<type>uint64_t</type>) - <literal>r-</literal> - [<option>--enable-stats</option>] - </term> - <listitem><para>Cumulative number of allocation requests satisfied by - bin regions of the corresponding size class.</para></listitem> - </varlistentry> - - <varlistentry id="stats.arenas.i.bins.j.curregs"> - <term> - <mallctl>stats.arenas.<i>.bins.<j>.curregs</mallctl> - (<type>size_t</type>) - <literal>r-</literal> - [<option>--enable-stats</option>] - </term> - <listitem><para>Current number of regions for this size - class.</para></listitem> - </varlistentry> - - <varlistentry id="stats.arenas.i.bins.j.nfills"> - <term> - <mallctl>stats.arenas.<i>.bins.<j>.nfills</mallctl> - (<type>uint64_t</type>) - <literal>r-</literal> - </term> - <listitem><para>Cumulative number of tcache fills.</para></listitem> - </varlistentry> - - <varlistentry id="stats.arenas.i.bins.j.nflushes"> - <term> - <mallctl>stats.arenas.<i>.bins.<j>.nflushes</mallctl> - (<type>uint64_t</type>) - <literal>r-</literal> - </term> - <listitem><para>Cumulative number of tcache flushes.</para></listitem> - </varlistentry> - - <varlistentry id="stats.arenas.i.bins.j.nslabs"> - <term> - <mallctl>stats.arenas.<i>.bins.<j>.nslabs</mallctl> - (<type>uint64_t</type>) - <literal>r-</literal> - [<option>--enable-stats</option>] - </term> - <listitem><para>Cumulative number of slabs created.</para></listitem> - </varlistentry> - - <varlistentry id="stats.arenas.i.bins.j.nreslabs"> - <term> - <mallctl>stats.arenas.<i>.bins.<j>.nreslabs</mallctl> - (<type>uint64_t</type>) - <literal>r-</literal> - [<option>--enable-stats</option>] - </term> - <listitem><para>Cumulative number of times the current slab from which - to allocate changed.</para></listitem> - </varlistentry> - - <varlistentry id="stats.arenas.i.bins.j.curslabs"> - <term> - <mallctl>stats.arenas.<i>.bins.<j>.curslabs</mallctl> - (<type>size_t</type>) - <literal>r-</literal> - [<option>--enable-stats</option>] - </term> - <listitem><para>Current number of slabs.</para></listitem> - </varlistentry> - - - <varlistentry id="stats.arenas.i.bins.j.nonfull_slabs"> - <term> - <mallctl>stats.arenas.<i>.bins.<j>.nonfull_slabs</mallctl> - (<type>size_t</type>) - <literal>r-</literal> - [<option>--enable-stats</option>] - </term> - <listitem><para>Current number of nonfull slabs.</para></listitem> - </varlistentry> - - <varlistentry id="stats.arenas.i.bins.mutex"> - <term> - <mallctl>stats.arenas.<i>.bins.<j>.mutex.{counter}</mallctl> - (<type>counter specific type</type>) <literal>r-</literal> - [<option>--enable-stats</option>] - </term> - <listitem><para>Statistics on - <varname>arena.<i>.bins.<j></varname> mutex (arena bin - scope; bin operation related). <mallctl>{counter}</mallctl> is one of - the counters in <link linkend="mutex_counters">mutex profiling - counters</link>.</para></listitem> - </varlistentry> - - <varlistentry id="stats.arenas.i.extents.n"> - <term> - <mallctl>stats.arenas.<i>.extents.<j>.n{extent_type}</mallctl> - (<type>size_t</type>) - <literal>r-</literal> - [<option>--enable-stats</option>] - </term> - <listitem><para> Number of extents of the given type in this arena in - the bucket corresponding to page size index <j>. The extent type - is one of dirty, muzzy, or retained.</para></listitem> - </varlistentry> - - <varlistentry id="stats.arenas.i.extents.bytes"> - <term> - <mallctl>stats.arenas.<i>.extents.<j>.{extent_type}_bytes</mallctl> - (<type>size_t</type>) - <literal>r-</literal> - [<option>--enable-stats</option>] - </term> - <listitem><para> Sum of the bytes managed by extents of the given type - in this arena in the bucket corresponding to page size index <j>. - The extent type is one of dirty, muzzy, or retained.</para></listitem> - </varlistentry> - - <varlistentry id="stats.arenas.i.lextents.j.nmalloc"> - <term> - <mallctl>stats.arenas.<i>.lextents.<j>.nmalloc</mallctl> - (<type>uint64_t</type>) - <literal>r-</literal> - [<option>--enable-stats</option>] - </term> - <listitem><para>Cumulative number of times a large extent of the - corresponding size class was allocated from the arena, whether to fill - the relevant tcache if <link - linkend="opt.tcache"><mallctl>opt.tcache</mallctl></link> is enabled and - the size class is within the range being cached, or to directly satisfy - an allocation request otherwise.</para></listitem> - </varlistentry> - - <varlistentry id="stats.arenas.i.lextents.j.ndalloc"> - <term> - <mallctl>stats.arenas.<i>.lextents.<j>.ndalloc</mallctl> - (<type>uint64_t</type>) - <literal>r-</literal> - [<option>--enable-stats</option>] - </term> - <listitem><para>Cumulative number of times a large extent of the - corresponding size class was returned to the arena, whether to flush the - relevant tcache if <link - linkend="opt.tcache"><mallctl>opt.tcache</mallctl></link> is enabled and - the size class is within the range being cached, or to directly - deallocate an allocation otherwise.</para></listitem> - </varlistentry> - - <varlistentry id="stats.arenas.i.lextents.j.nrequests"> - <term> - <mallctl>stats.arenas.<i>.lextents.<j>.nrequests</mallctl> - (<type>uint64_t</type>) - <literal>r-</literal> - [<option>--enable-stats</option>] - </term> - <listitem><para>Cumulative number of allocation requests satisfied by - large extents of the corresponding size class.</para></listitem> - </varlistentry> - - <varlistentry id="stats.arenas.i.lextents.j.curlextents"> - <term> - <mallctl>stats.arenas.<i>.lextents.<j>.curlextents</mallctl> - (<type>size_t</type>) - <literal>r-</literal> - [<option>--enable-stats</option>] - </term> - <listitem><para>Current number of large allocations for this size class. - </para></listitem> - </varlistentry> - - <varlistentry id="stats.arenas.i.mutexes.large"> - <term> - <mallctl>stats.arenas.<i>.mutexes.large.{counter}</mallctl> - (<type>counter specific type</type>) <literal>r-</literal> - [<option>--enable-stats</option>] - </term> - <listitem><para>Statistics on <varname>arena.<i>.large</varname> - mutex (arena scope; large allocation related). - <mallctl>{counter}</mallctl> is one of the counters in <link - linkend="mutex_counters">mutex profiling - counters</link>.</para></listitem> - </varlistentry> - - <varlistentry id="stats.arenas.i.mutexes.extent_avail"> - <term> - <mallctl>stats.arenas.<i>.mutexes.extent_avail.{counter}</mallctl> - (<type>counter specific type</type>) <literal>r-</literal> - [<option>--enable-stats</option>] - </term> - <listitem><para>Statistics on <varname>arena.<i>.extent_avail - </varname> mutex (arena scope; extent avail related). - <mallctl>{counter}</mallctl> is one of the counters in <link - linkend="mutex_counters">mutex profiling - counters</link>.</para></listitem> - </varlistentry> - - <varlistentry id="stats.arenas.i.mutexes.extents_dirty"> - <term> - <mallctl>stats.arenas.<i>.mutexes.extents_dirty.{counter}</mallctl> - (<type>counter specific type</type>) <literal>r-</literal> - [<option>--enable-stats</option>] - </term> - <listitem><para>Statistics on <varname>arena.<i>.extents_dirty - </varname> mutex (arena scope; dirty extents related). - <mallctl>{counter}</mallctl> is one of the counters in <link - linkend="mutex_counters">mutex profiling - counters</link>.</para></listitem> - </varlistentry> - - <varlistentry id="stats.arenas.i.mutexes.extents_muzzy"> - <term> - <mallctl>stats.arenas.<i>.mutexes.extents_muzzy.{counter}</mallctl> - (<type>counter specific type</type>) <literal>r-</literal> - [<option>--enable-stats</option>] - </term> - <listitem><para>Statistics on <varname>arena.<i>.extents_muzzy - </varname> mutex (arena scope; muzzy extents related). - <mallctl>{counter}</mallctl> is one of the counters in <link - linkend="mutex_counters">mutex profiling - counters</link>.</para></listitem> - </varlistentry> - - <varlistentry id="stats.arenas.i.mutexes.extents_retained"> - <term> - <mallctl>stats.arenas.<i>.mutexes.extents_retained.{counter}</mallctl> - (<type>counter specific type</type>) <literal>r-</literal> - [<option>--enable-stats</option>] - </term> - <listitem><para>Statistics on <varname>arena.<i>.extents_retained - </varname> mutex (arena scope; retained extents related). - <mallctl>{counter}</mallctl> is one of the counters in <link - linkend="mutex_counters">mutex profiling - counters</link>.</para></listitem> - </varlistentry> - - <varlistentry id="stats.arenas.i.mutexes.decay_dirty"> - <term> - <mallctl>stats.arenas.<i>.mutexes.decay_dirty.{counter}</mallctl> - (<type>counter specific type</type>) <literal>r-</literal> - [<option>--enable-stats</option>] - </term> - <listitem><para>Statistics on <varname>arena.<i>.decay_dirty - </varname> mutex (arena scope; decay for dirty pages related). - <mallctl>{counter}</mallctl> is one of the counters in <link - linkend="mutex_counters">mutex profiling - counters</link>.</para></listitem> - </varlistentry> - - <varlistentry id="stats.arenas.i.mutexes.decay_muzzy"> - <term> - <mallctl>stats.arenas.<i>.mutexes.decay_muzzy.{counter}</mallctl> - (<type>counter specific type</type>) <literal>r-</literal> - [<option>--enable-stats</option>] - </term> - <listitem><para>Statistics on <varname>arena.<i>.decay_muzzy - </varname> mutex (arena scope; decay for muzzy pages related). - <mallctl>{counter}</mallctl> is one of the counters in <link - linkend="mutex_counters">mutex profiling - counters</link>.</para></listitem> - </varlistentry> - - <varlistentry id="stats.arenas.i.mutexes.base"> - <term> - <mallctl>stats.arenas.<i>.mutexes.base.{counter}</mallctl> - (<type>counter specific type</type>) <literal>r-</literal> - [<option>--enable-stats</option>] - </term> - <listitem><para>Statistics on <varname>arena.<i>.base</varname> - mutex (arena scope; base allocator related). - <mallctl>{counter}</mallctl> is one of the counters in <link - linkend="mutex_counters">mutex profiling - counters</link>.</para></listitem> - </varlistentry> - - <varlistentry id="stats.arenas.i.mutexes.tcache_list"> - <term> - <mallctl>stats.arenas.<i>.mutexes.tcache_list.{counter}</mallctl> - (<type>counter specific type</type>) <literal>r-</literal> - [<option>--enable-stats</option>] - </term> - <listitem><para>Statistics on - <varname>arena.<i>.tcache_list</varname> mutex (arena scope; - tcache to arena association related). This mutex is expected to be - accessed less often. <mallctl>{counter}</mallctl> is one of the - counters in <link linkend="mutex_counters">mutex profiling - counters</link>.</para></listitem> - </varlistentry> - - </variablelist> - </refsect1> - <refsect1 id="heap_profile_format"> - <title>HEAP PROFILE FORMAT</title> - <para>Although the heap profiling functionality was originally designed to - be compatible with the - <command>pprof</command> command that is developed as part of the <ulink - url="http://code.google.com/p/gperftools/">gperftools - package</ulink>, the addition of per thread heap profiling functionality - required a different heap profile format. The <command>jeprof</command> - command is derived from <command>pprof</command>, with enhancements to - support the heap profile format described here.</para> - - <para>In the following hypothetical heap profile, <constant>[...]</constant> - indicates elision for the sake of compactness. <programlisting><![CDATA[ -heap_v2/524288 - t*: 28106: 56637512 [0: 0] - [...] - t3: 352: 16777344 [0: 0] - [...] - t99: 17754: 29341640 [0: 0] - [...] -@ 0x5f86da8 0x5f5a1dc [...] 0x29e4d4e 0xa200316 0xabb2988 [...] - t*: 13: 6688 [0: 0] - t3: 12: 6496 [0: ] - t99: 1: 192 [0: 0] -[...] - -MAPPED_LIBRARIES: -[...]]]></programlisting> The following matches the above heap profile, but most -tokens are replaced with <constant><description></constant> to indicate -descriptions of the corresponding fields. <programlisting><![CDATA[ -<heap_profile_format_version>/<mean_sample_interval> - <aggregate>: <curobjs>: <curbytes> [<cumobjs>: <cumbytes>] - [...] - <thread_3_aggregate>: <curobjs>: <curbytes>[<cumobjs>: <cumbytes>] - [...] - <thread_99_aggregate>: <curobjs>: <curbytes>[<cumobjs>: <cumbytes>] - [...] -@ <top_frame> <frame> [...] <frame> <frame> <frame> [...] - <backtrace_aggregate>: <curobjs>: <curbytes> [<cumobjs>: <cumbytes>] - <backtrace_thread_3>: <curobjs>: <curbytes> [<cumobjs>: <cumbytes>] - <backtrace_thread_99>: <curobjs>: <curbytes> [<cumobjs>: <cumbytes>] -[...] - -MAPPED_LIBRARIES: -</proc/<pid>/maps>]]></programlisting></para> - </refsect1> - - <refsect1 id="debugging_malloc_problems"> - <title>DEBUGGING MALLOC PROBLEMS</title> - <para>When debugging, it is a good idea to configure/build jemalloc with - the <option>--enable-debug</option> and <option>--enable-fill</option> - options, and recompile the program with suitable options and symbols for - debugger support. When so configured, jemalloc incorporates a wide variety - of run-time assertions that catch application errors such as double-free, - write-after-free, etc.</para> - - <para>Programs often accidentally depend on <quote>uninitialized</quote> - memory actually being filled with zero bytes. Junk filling - (see the <link linkend="opt.junk"><mallctl>opt.junk</mallctl></link> - option) tends to expose such bugs in the form of obviously incorrect - results and/or coredumps. Conversely, zero - filling (see the <link - linkend="opt.zero"><mallctl>opt.zero</mallctl></link> option) eliminates - the symptoms of such bugs. Between these two options, it is usually - possible to quickly detect, diagnose, and eliminate such bugs.</para> - - <para>This implementation does not provide much detail about the problems - it detects, because the performance impact for storing such information - would be prohibitive.</para> - </refsect1> - <refsect1 id="diagnostic_messages"> - <title>DIAGNOSTIC MESSAGES</title> - <para>If any of the memory allocation/deallocation functions detect an - error or warning condition, a message will be printed to file descriptor - <constant>STDERR_FILENO</constant>. Errors will result in the process - dumping core. If the <link - linkend="opt.abort"><mallctl>opt.abort</mallctl></link> option is set, most - warnings are treated as errors.</para> - - <para>The <varname>malloc_message</varname> variable allows the programmer - to override the function which emits the text strings forming the errors - and warnings if for some reason the <constant>STDERR_FILENO</constant> file - descriptor is not suitable for this. - <function>malloc_message()</function> takes the - <parameter>cbopaque</parameter> pointer argument that is - <constant>NULL</constant> unless overridden by the arguments in a call to - <function>malloc_stats_print()</function>, followed by a string - pointer. Please note that doing anything which tries to allocate memory in - this function is likely to result in a crash or deadlock.</para> - - <para>All messages are prefixed by - <quote><computeroutput><jemalloc>: </computeroutput></quote>.</para> - </refsect1> - <refsect1 id="return_values"> - <title>RETURN VALUES</title> - <refsect2> - <title>Standard API</title> - <para>The <function>malloc()</function> and - <function>calloc()</function> functions return a pointer to the - allocated memory if successful; otherwise a <constant>NULL</constant> - pointer is returned and <varname>errno</varname> is set to - <errorname>ENOMEM</errorname>.</para> - - <para>The <function>posix_memalign()</function> function - returns the value 0 if successful; otherwise it returns an error value. - The <function>posix_memalign()</function> function will fail - if: - <variablelist> - <varlistentry> - <term><errorname>EINVAL</errorname></term> - - <listitem><para>The <parameter>alignment</parameter> parameter is - not a power of 2 at least as large as - <code language="C">sizeof(<type>void *</type>)</code>. - </para></listitem> - </varlistentry> - <varlistentry> - <term><errorname>ENOMEM</errorname></term> - - <listitem><para>Memory allocation error.</para></listitem> - </varlistentry> - </variablelist> - </para> - - <para>The <function>aligned_alloc()</function> function returns - a pointer to the allocated memory if successful; otherwise a - <constant>NULL</constant> pointer is returned and - <varname>errno</varname> is set. The - <function>aligned_alloc()</function> function will fail if: - <variablelist> - <varlistentry> - <term><errorname>EINVAL</errorname></term> - - <listitem><para>The <parameter>alignment</parameter> parameter is - not a power of 2. - </para></listitem> - </varlistentry> - <varlistentry> - <term><errorname>ENOMEM</errorname></term> - - <listitem><para>Memory allocation error.</para></listitem> - </varlistentry> - </variablelist> - </para> - - <para>The <function>realloc()</function> function returns a - pointer, possibly identical to <parameter>ptr</parameter>, to the - allocated memory if successful; otherwise a <constant>NULL</constant> - pointer is returned, and <varname>errno</varname> is set to - <errorname>ENOMEM</errorname> if the error was the result of an - allocation failure. The <function>realloc()</function> - function always leaves the original buffer intact when an error occurs. - </para> - - <para>The <function>free()</function> function returns no - value.</para> - </refsect2> - <refsect2> - <title>Non-standard API</title> - <para>The <function>mallocx()</function> and - <function>rallocx()</function> functions return a pointer to - the allocated memory if successful; otherwise a <constant>NULL</constant> - pointer is returned to indicate insufficient contiguous memory was - available to service the allocation request. </para> - - <para>The <function>xallocx()</function> function returns the - real size of the resulting resized allocation pointed to by - <parameter>ptr</parameter>, which is a value less than - <parameter>size</parameter> if the allocation could not be adequately - grown in place. </para> - - <para>The <function>sallocx()</function> function returns the - real size of the allocation pointed to by <parameter>ptr</parameter>. - </para> - - <para>The <function>nallocx()</function> returns the real size - that would result from a successful equivalent - <function>mallocx()</function> function call, or zero if - insufficient memory is available to perform the size computation. </para> - - <para>The <function>mallctl()</function>, - <function>mallctlnametomib()</function>, and - <function>mallctlbymib()</function> functions return 0 on - success; otherwise they return an error value. The functions will fail - if: - <variablelist> - <varlistentry> - <term><errorname>EINVAL</errorname></term> - - <listitem><para><parameter>newp</parameter> is not - <constant>NULL</constant>, and <parameter>newlen</parameter> is too - large or too small. Alternatively, <parameter>*oldlenp</parameter> - is too large or too small; in this case as much data as possible - are read despite the error.</para></listitem> - </varlistentry> - <varlistentry> - <term><errorname>ENOENT</errorname></term> - - <listitem><para><parameter>name</parameter> or - <parameter>mib</parameter> specifies an unknown/invalid - value.</para></listitem> - </varlistentry> - <varlistentry> - <term><errorname>EPERM</errorname></term> - - <listitem><para>Attempt to read or write void value, or attempt to - write read-only value.</para></listitem> - </varlistentry> - <varlistentry> - <term><errorname>EAGAIN</errorname></term> - - <listitem><para>A memory allocation failure - occurred.</para></listitem> - </varlistentry> - <varlistentry> - <term><errorname>EFAULT</errorname></term> - - <listitem><para>An interface with side effects failed in some way - not directly related to <function>mallctl*()</function> - read/write processing.</para></listitem> - </varlistentry> - </variablelist> - </para> - - <para>The <function>malloc_usable_size()</function> function - returns the usable size of the allocation pointed to by - <parameter>ptr</parameter>. </para> - </refsect2> - </refsect1> - <refsect1 id="environment"> - <title>ENVIRONMENT</title> - <para>The following environment variable affects the execution of the - allocation functions: - <variablelist> - <varlistentry> - <term><envar>MALLOC_CONF</envar></term> - - <listitem><para>If the environment variable - <envar>MALLOC_CONF</envar> is set, the characters it contains - will be interpreted as options.</para></listitem> - </varlistentry> - </variablelist> - </para> - </refsect1> - <refsect1 id="examples"> - <title>EXAMPLES</title> - <para>To dump core whenever a problem occurs: - <screen>ln -s 'abort:true' /etc/malloc.conf</screen> - </para> - <para>To specify in the source that only one arena should be automatically - created: - <programlisting language="C"><![CDATA[ -malloc_conf = "narenas:1";]]></programlisting></para> - </refsect1> - <refsect1 id="see_also"> - <title>SEE ALSO</title> - <para><citerefentry><refentrytitle>madvise</refentrytitle> - <manvolnum>2</manvolnum></citerefentry>, - <citerefentry><refentrytitle>mmap</refentrytitle> - <manvolnum>2</manvolnum></citerefentry>, - <citerefentry><refentrytitle>sbrk</refentrytitle> - <manvolnum>2</manvolnum></citerefentry>, - <citerefentry><refentrytitle>utrace</refentrytitle> - <manvolnum>2</manvolnum></citerefentry>, - <citerefentry><refentrytitle>alloca</refentrytitle> - <manvolnum>3</manvolnum></citerefentry>, - <citerefentry><refentrytitle>atexit</refentrytitle> - <manvolnum>3</manvolnum></citerefentry>, - <citerefentry><refentrytitle>getpagesize</refentrytitle> - <manvolnum>3</manvolnum></citerefentry></para> - </refsect1> - <refsect1 id="standards"> - <title>STANDARDS</title> - <para>The <function>malloc()</function>, - <function>calloc()</function>, - <function>realloc()</function>, and - <function>free()</function> functions conform to ISO/IEC - 9899:1990 (<quote>ISO C90</quote>).</para> - - <para>The <function>posix_memalign()</function> function conforms - to IEEE Std 1003.1-2001 (<quote>POSIX.1</quote>).</para> - </refsect1> - <refsect1 id="history"> - <title>HISTORY</title> - <para>The <function>malloc_usable_size()</function> and - <function>posix_memalign()</function> functions first appeared in FreeBSD - 7.0.</para> - - <para>The <function>aligned_alloc()</function>, - <function>malloc_stats_print()</function>, and - <function>mallctl*()</function> functions first appeared in FreeBSD - 10.0.</para> - - <para>The <function>*allocx()</function> functions first appeared in FreeBSD - 11.0.</para> - </refsect1> -</refentry> ->>>>>>> main diff --git a/contrib/jemalloc/include/jemalloc/internal/jemalloc_internal_defs.h.in b/contrib/jemalloc/include/jemalloc/internal/jemalloc_internal_defs.h.in index 52b31878a464..3588072f178c 100644 --- a/contrib/jemalloc/include/jemalloc/internal/jemalloc_internal_defs.h.in +++ b/contrib/jemalloc/include/jemalloc/internal/jemalloc_internal_defs.h.in @@ -1,4 +1,3 @@ -<<<<<<< HEAD #ifndef JEMALLOC_INTERNAL_DEFS_H_ #define JEMALLOC_INTERNAL_DEFS_H_ /* @@ -426,372 +425,3 @@ #undef JEMALLOC_ZERO_REALLOC_DEFAULT_FREE #endif /* JEMALLOC_INTERNAL_DEFS_H_ */ -||||||| dec341af7695 -======= -#ifndef JEMALLOC_INTERNAL_DEFS_H_ -#define JEMALLOC_INTERNAL_DEFS_H_ -/* - * If JEMALLOC_PREFIX is defined via --with-jemalloc-prefix, it will cause all - * public APIs to be prefixed. This makes it possible, with some care, to use - * multiple allocators simultaneously. - */ -#undef JEMALLOC_PREFIX -#undef JEMALLOC_CPREFIX - -/* - * Define overrides for non-standard allocator-related functions if they are - * present on the system. - */ -#undef JEMALLOC_OVERRIDE___LIBC_CALLOC -#undef JEMALLOC_OVERRIDE___LIBC_FREE -#undef JEMALLOC_OVERRIDE___LIBC_MALLOC -#undef JEMALLOC_OVERRIDE___LIBC_MEMALIGN -#undef JEMALLOC_OVERRIDE___LIBC_REALLOC -#undef JEMALLOC_OVERRIDE___LIBC_VALLOC -#undef JEMALLOC_OVERRIDE___POSIX_MEMALIGN - -/* - * JEMALLOC_PRIVATE_NAMESPACE is used as a prefix for all library-private APIs. - * For shared libraries, symbol visibility mechanisms prevent these symbols - * from being exported, but for static libraries, naming collisions are a real - * possibility. - */ -#undef JEMALLOC_PRIVATE_NAMESPACE - -/* - * Hyper-threaded CPUs may need a special instruction inside spin loops in - * order to yield to another virtual CPU. - */ -#undef CPU_SPINWAIT -/* 1 if CPU_SPINWAIT is defined, 0 otherwise. */ -#undef HAVE_CPU_SPINWAIT - -/* - * Number of significant bits in virtual addresses. This may be less than the - * total number of bits in a pointer, e.g. on x64, for which the uppermost 16 - * bits are the same as bit 47. - */ -#undef LG_VADDR - -/* Defined if C11 atomics are available. */ -#undef JEMALLOC_C11_ATOMICS - -/* Defined if GCC __atomic atomics are available. */ -#undef JEMALLOC_GCC_ATOMIC_ATOMICS -/* and the 8-bit variant support. */ -#undef JEMALLOC_GCC_U8_ATOMIC_ATOMICS - -/* Defined if GCC __sync atomics are available. */ -#undef JEMALLOC_GCC_SYNC_ATOMICS -/* and the 8-bit variant support. */ -#undef JEMALLOC_GCC_U8_SYNC_ATOMICS - -/* - * Defined if __builtin_clz() and __builtin_clzl() are available. - */ -#undef JEMALLOC_HAVE_BUILTIN_CLZ - -/* - * Defined if os_unfair_lock_*() functions are available, as provided by Darwin. - */ -#undef JEMALLOC_OS_UNFAIR_LOCK - -/* Defined if syscall(2) is usable. */ -#undef JEMALLOC_USE_SYSCALL - -/* - * Defined if secure_getenv(3) is available. - */ -#undef JEMALLOC_HAVE_SECURE_GETENV - -/* - * Defined if issetugid(2) is available. - */ -#undef JEMALLOC_HAVE_ISSETUGID - -/* Defined if pthread_atfork(3) is available. */ -#undef JEMALLOC_HAVE_PTHREAD_ATFORK - -/* Defined if pthread_setname_np(3) is available. */ -#undef JEMALLOC_HAVE_PTHREAD_SETNAME_NP - -/* - * Defined if clock_gettime(CLOCK_MONOTONIC_COARSE, ...) is available. - */ -#undef JEMALLOC_HAVE_CLOCK_MONOTONIC_COARSE - -/* - * Defined if clock_gettime(CLOCK_MONOTONIC, ...) is available. - */ -#undef JEMALLOC_HAVE_CLOCK_MONOTONIC - -/* - * Defined if mach_absolute_time() is available. - */ -#undef JEMALLOC_HAVE_MACH_ABSOLUTE_TIME - -/* - * Defined if _malloc_thread_cleanup() exists. At least in the case of - * FreeBSD, pthread_key_create() allocates, which if used during malloc - * bootstrapping will cause recursion into the pthreads library. Therefore, if - * _malloc_thread_cleanup() exists, use it as the basis for thread cleanup in - * malloc_tsd. - */ -#undef JEMALLOC_MALLOC_THREAD_CLEANUP - -/* - * Defined if threaded initialization is known to be safe on this platform. - * Among other things, it must be possible to initialize a mutex without - * triggering allocation in order for threaded allocation to be safe. - */ -#undef JEMALLOC_THREADED_INIT - -/* - * Defined if the pthreads implementation defines - * _pthread_mutex_init_calloc_cb(), in which case the function is used in order - * to avoid recursive allocation during mutex initialization. - */ -#undef JEMALLOC_MUTEX_INIT_CB - -/* Non-empty if the tls_model attribute is supported. */ -#undef JEMALLOC_TLS_MODEL - -/* - * JEMALLOC_DEBUG enables assertions and other sanity checks, and disables - * inline functions. - */ -#undef JEMALLOC_DEBUG - -/* JEMALLOC_STATS enables statistics calculation. */ -#undef JEMALLOC_STATS - -/* JEMALLOC_EXPERIMENTAL_SMALLOCX_API enables experimental smallocx API. */ -#undef JEMALLOC_EXPERIMENTAL_SMALLOCX_API - -/* JEMALLOC_PROF enables allocation profiling. */ -#undef JEMALLOC_PROF - -/* Use libunwind for profile backtracing if defined. */ -#undef JEMALLOC_PROF_LIBUNWIND - -/* Use libgcc for profile backtracing if defined. */ -#undef JEMALLOC_PROF_LIBGCC - -/* Use gcc intrinsics for profile backtracing if defined. */ -#undef JEMALLOC_PROF_GCC - -/* - * JEMALLOC_DSS enables use of sbrk(2) to allocate extents from the data storage - * segment (DSS). - */ -#undef JEMALLOC_DSS - -/* Support memory filling (junk/zero). */ -#undef JEMALLOC_FILL - -/* Support utrace(2)-based tracing. */ -#undef JEMALLOC_UTRACE - -/* Support optional abort() on OOM. */ -#undef JEMALLOC_XMALLOC - -/* Support lazy locking (avoid locking unless a second thread is launched). */ -#undef JEMALLOC_LAZY_LOCK - -/* - * Minimum allocation alignment is 2^LG_QUANTUM bytes (ignoring tiny size - * classes). - */ -#undef LG_QUANTUM - -/* One page is 2^LG_PAGE bytes. */ -#undef LG_PAGE - -/* - * One huge page is 2^LG_HUGEPAGE bytes. Note that this is defined even if the - * system does not explicitly support huge pages; system calls that require - * explicit huge page support are separately configured. - */ -#undef LG_HUGEPAGE - -/* - * If defined, adjacent virtual memory mappings with identical attributes - * automatically coalesce, and they fragment when changes are made to subranges. - * This is the normal order of things for mmap()/munmap(), but on Windows - * VirtualAlloc()/VirtualFree() operations must be precisely matched, i.e. - * mappings do *not* coalesce/fragment. - */ -#undef JEMALLOC_MAPS_COALESCE - -/* - * If defined, retain memory for later reuse by default rather than using e.g. - * munmap() to unmap freed extents. This is enabled on 64-bit Linux because - * common sequences of mmap()/munmap() calls will cause virtual memory map - * holes. - */ -#undef JEMALLOC_RETAIN - -/* TLS is used to map arenas and magazine caches to threads. */ -#undef JEMALLOC_TLS - -/* - * Used to mark unreachable code to quiet "end of non-void" compiler warnings. - * Don't use this directly; instead use unreachable() from util.h - */ -#undef JEMALLOC_INTERNAL_UNREACHABLE - -/* - * ffs*() functions to use for bitmapping. Don't use these directly; instead, - * use ffs_*() from util.h. - */ -#undef JEMALLOC_INTERNAL_FFSLL -#undef JEMALLOC_INTERNAL_FFSL -#undef JEMALLOC_INTERNAL_FFS - -/* - * popcount*() functions to use for bitmapping. - */ -#undef JEMALLOC_INTERNAL_POPCOUNTL -#undef JEMALLOC_INTERNAL_POPCOUNT - -/* - * If defined, explicitly attempt to more uniformly distribute large allocation - * pointer alignments across all cache indices. - */ -#undef JEMALLOC_CACHE_OBLIVIOUS - -/* - * If defined, enable logging facilities. We make this a configure option to - * avoid taking extra branches everywhere. - */ -#undef JEMALLOC_LOG - -/* - * If defined, use readlinkat() (instead of readlink()) to follow - * /etc/malloc_conf. - */ -#undef JEMALLOC_READLINKAT - -/* - * Darwin (OS X) uses zones to work around Mach-O symbol override shortcomings. - */ -#undef JEMALLOC_ZONE - -/* - * Methods for determining whether the OS overcommits. - * JEMALLOC_PROC_SYS_VM_OVERCOMMIT_MEMORY: Linux's - * /proc/sys/vm.overcommit_memory file. - * JEMALLOC_SYSCTL_VM_OVERCOMMIT: FreeBSD's vm.overcommit sysctl. - */ -#undef JEMALLOC_SYSCTL_VM_OVERCOMMIT -#undef JEMALLOC_PROC_SYS_VM_OVERCOMMIT_MEMORY - -/* Defined if madvise(2) is available. */ -#undef JEMALLOC_HAVE_MADVISE - -/* - * Defined if transparent huge pages are supported via the MADV_[NO]HUGEPAGE - * arguments to madvise(2). - */ -#undef JEMALLOC_HAVE_MADVISE_HUGE - -/* - * Methods for purging unused pages differ between operating systems. - * - * madvise(..., MADV_FREE) : This marks pages as being unused, such that they - * will be discarded rather than swapped out. - * madvise(..., MADV_DONTNEED) : If JEMALLOC_PURGE_MADVISE_DONTNEED_ZEROS is - * defined, this immediately discards pages, - * such that new pages will be demand-zeroed if - * the address region is later touched; - * otherwise this behaves similarly to - * MADV_FREE, though typically with higher - * system overhead. - */ -#undef JEMALLOC_PURGE_MADVISE_FREE -#undef JEMALLOC_PURGE_MADVISE_DONTNEED -#undef JEMALLOC_PURGE_MADVISE_DONTNEED_ZEROS - -/* Defined if madvise(2) is available but MADV_FREE is not (x86 Linux only). */ -#undef JEMALLOC_DEFINE_MADVISE_FREE - -/* - * Defined if MADV_DO[NT]DUMP is supported as an argument to madvise. - */ -#undef JEMALLOC_MADVISE_DONTDUMP - -/* - * Defined if transparent huge pages (THPs) are supported via the - * MADV_[NO]HUGEPAGE arguments to madvise(2), and THP support is enabled. - */ -#undef JEMALLOC_THP - -/* Define if operating system has alloca.h header. */ -#undef JEMALLOC_HAS_ALLOCA_H - -/* C99 restrict keyword supported. */ -#undef JEMALLOC_HAS_RESTRICT - -/* For use by hash code. */ -#undef JEMALLOC_BIG_ENDIAN - -/* sizeof(int) == 2^LG_SIZEOF_INT. */ -#undef LG_SIZEOF_INT - -/* sizeof(long) == 2^LG_SIZEOF_LONG. */ -#undef LG_SIZEOF_LONG - -/* sizeof(long long) == 2^LG_SIZEOF_LONG_LONG. */ -#undef LG_SIZEOF_LONG_LONG - -/* sizeof(intmax_t) == 2^LG_SIZEOF_INTMAX_T. */ -#undef LG_SIZEOF_INTMAX_T - -/* glibc malloc hooks (__malloc_hook, __realloc_hook, __free_hook). */ -#undef JEMALLOC_GLIBC_MALLOC_HOOK - -/* glibc memalign hook. */ -#undef JEMALLOC_GLIBC_MEMALIGN_HOOK - -/* pthread support */ -#undef JEMALLOC_HAVE_PTHREAD - -/* dlsym() support */ -#undef JEMALLOC_HAVE_DLSYM - -/* Adaptive mutex support in pthreads. */ -#undef JEMALLOC_HAVE_PTHREAD_MUTEX_ADAPTIVE_NP - -/* GNU specific sched_getcpu support */ -#undef JEMALLOC_HAVE_SCHED_GETCPU - -/* GNU specific sched_setaffinity support */ -#undef JEMALLOC_HAVE_SCHED_SETAFFINITY - -/* - * If defined, all the features necessary for background threads are present. - */ -#undef JEMALLOC_BACKGROUND_THREAD - -/* - * If defined, jemalloc symbols are not exported (doesn't work when - * JEMALLOC_PREFIX is not defined). - */ -#undef JEMALLOC_EXPORT - -/* config.malloc_conf options string. */ -#undef JEMALLOC_CONFIG_MALLOC_CONF - -/* If defined, jemalloc takes the malloc/free/etc. symbol names. */ -#undef JEMALLOC_IS_MALLOC - -/* - * Defined if strerror_r returns char * if _GNU_SOURCE is defined. - */ -#undef JEMALLOC_STRERROR_R_RETURNS_CHAR_WITH_GNU_SOURCE - -/* Performs additional safety checks when defined. */ -#undef JEMALLOC_OPT_SAFETY_CHECKS - -#endif /* JEMALLOC_INTERNAL_DEFS_H_ */ ->>>>>>> main diff --git a/contrib/jemalloc/include/jemalloc/internal/jemalloc_preamble.h.in b/contrib/jemalloc/include/jemalloc/internal/jemalloc_preamble.h.in index c4fb2d0793bf..e4932f1e8c18 100644 --- a/contrib/jemalloc/include/jemalloc/internal/jemalloc_preamble.h.in +++ b/contrib/jemalloc/include/jemalloc/internal/jemalloc_preamble.h.in @@ -1,4 +1,3 @@ -<<<<<<< HEAD #ifndef JEMALLOC_PREAMBLE_H #define JEMALLOC_PREAMBLE_H @@ -261,218 +260,3 @@ static const bool have_memcntl = ; #endif /* JEMALLOC_PREAMBLE_H */ -||||||| dec341af7695 -======= -#ifndef JEMALLOC_PREAMBLE_H -#define JEMALLOC_PREAMBLE_H - -#include "jemalloc_internal_defs.h" -#include "jemalloc/internal/jemalloc_internal_decls.h" - -#ifdef JEMALLOC_UTRACE -#include <sys/ktrace.h> -#endif - -#ifndef JEMALLOC_PRIVATE_NAMESPACE -#include "un-namespace.h" -#include "libc_private.h" -#endif - -#define JEMALLOC_NO_DEMANGLE -#ifdef JEMALLOC_JET -# undef JEMALLOC_IS_MALLOC -# define JEMALLOC_N(n) jet_##n -# include "jemalloc/internal/public_namespace.h" -# define JEMALLOC_NO_RENAME -# include "../jemalloc@install_suffix@.h" -# undef JEMALLOC_NO_RENAME -#else -# define JEMALLOC_N(n) @private_namespace@##n -# include "../jemalloc@install_suffix@.h" -#endif - -#if defined(JEMALLOC_OSATOMIC) -#include <libkern/OSAtomic.h> -#endif - -#ifdef JEMALLOC_ZONE -#include <mach/mach_error.h> -#include <mach/mach_init.h> -#include <mach/vm_map.h> -#endif - -#include "jemalloc/internal/jemalloc_internal_macros.h" - -/* - * Note that the ordering matters here; the hook itself is name-mangled. We - * want the inclusion of hooks to happen early, so that we hook as much as - * possible. - */ -#ifndef JEMALLOC_NO_PRIVATE_NAMESPACE -# ifndef JEMALLOC_JET -# include "jemalloc/internal/private_namespace.h" -# else -# include "jemalloc/internal/private_namespace_jet.h" -# endif -#endif -#include "jemalloc/internal/test_hooks.h" - -#ifdef JEMALLOC_DEFINE_MADVISE_FREE -# define JEMALLOC_MADV_FREE 8 -#endif - -static const bool config_debug = -#ifdef JEMALLOC_DEBUG - true -#else - false -#endif - ; -static const bool have_dss = -#ifdef JEMALLOC_DSS - true -#else - false -#endif - ; -static const bool have_madvise_huge = -#ifdef JEMALLOC_HAVE_MADVISE_HUGE - true -#else - false -#endif - ; -static const bool config_fill = -#ifdef JEMALLOC_FILL - true -#else - false -#endif - ; -static const bool config_lazy_lock = true; -static const char * const config_malloc_conf = JEMALLOC_CONFIG_MALLOC_CONF; -static const bool config_prof = -#ifdef JEMALLOC_PROF - true -#else - false -#endif - ; -static const bool config_prof_libgcc = -#ifdef JEMALLOC_PROF_LIBGCC - true -#else - false -#endif - ; -static const bool config_prof_libunwind = -#ifdef JEMALLOC_PROF_LIBUNWIND - true -#else - false -#endif - ; -static const bool maps_coalesce = -#ifdef JEMALLOC_MAPS_COALESCE - true -#else - false -#endif - ; -static const bool config_stats = -#ifdef JEMALLOC_STATS - true -#else - false -#endif - ; -static const bool config_tls = -#ifdef JEMALLOC_TLS - true -#else - false -#endif - ; -static const bool config_utrace = -#ifdef JEMALLOC_UTRACE - true -#else - false -#endif - ; -static const bool config_xmalloc = -#ifdef JEMALLOC_XMALLOC - true -#else - false -#endif - ; -static const bool config_cache_oblivious = -#ifdef JEMALLOC_CACHE_OBLIVIOUS - true -#else - false -#endif - ; -/* - * Undocumented, for jemalloc development use only at the moment. See the note - * in jemalloc/internal/log.h. - */ -static const bool config_log = -#ifdef JEMALLOC_LOG - true -#else - false -#endif - ; -/* - * Are extra safety checks enabled; things like checking the size of sized - * deallocations, double-frees, etc. - */ -static const bool config_opt_safety_checks = -#ifdef JEMALLOC_OPT_SAFETY_CHECKS - true -#elif defined(JEMALLOC_DEBUG) - /* - * This lets us only guard safety checks by one flag instead of two; fast - * checks can guard solely by config_opt_safety_checks and run in debug mode - * too. - */ - true -#else - false -#endif - ; - -#if defined(_WIN32) || defined(JEMALLOC_HAVE_SCHED_GETCPU) -/* Currently percpu_arena depends on sched_getcpu. */ -#define JEMALLOC_PERCPU_ARENA -#endif -static const bool have_percpu_arena = -#ifdef JEMALLOC_PERCPU_ARENA - true -#else - false -#endif - ; -/* - * Undocumented, and not recommended; the application should take full - * responsibility for tracking provenance. - */ -static const bool force_ivsalloc = -#ifdef JEMALLOC_FORCE_IVSALLOC - true -#else - false -#endif - ; -static const bool have_background_thread = -#ifdef JEMALLOC_BACKGROUND_THREAD - true -#else - false -#endif - ; - -#endif /* JEMALLOC_PREAMBLE_H */ ->>>>>>> main diff --git a/contrib/jemalloc/include/jemalloc/internal/tsd_win.h b/contrib/jemalloc/include/jemalloc/internal/tsd_win.h index 46be2434b5a5..a91dac88e06a 100644 --- a/contrib/jemalloc/include/jemalloc/internal/tsd_win.h +++ b/contrib/jemalloc/include/jemalloc/internal/tsd_win.h @@ -1,4 +1,3 @@ -<<<<<<< HEAD #ifdef JEMALLOC_INTERNAL_TSD_WIN_H #error This file should be included only once, by tsd.h. #endif @@ -138,145 +137,3 @@ tsd_set(tsd_t *val) { } wrapper->initialized = true; } -||||||| dec341af7695 -======= -#ifdef JEMALLOC_INTERNAL_TSD_WIN_H -#error This file should be included only once, by tsd.h. -#endif -#define JEMALLOC_INTERNAL_TSD_WIN_H - -typedef struct { - bool initialized; - tsd_t val; -} tsd_wrapper_t; - -extern DWORD tsd_tsd; -extern tsd_wrapper_t tsd_boot_wrapper; -extern bool tsd_booted; - -/* Initialization/cleanup. */ -JEMALLOC_ALWAYS_INLINE bool -tsd_cleanup_wrapper(void) { - DWORD error = GetLastError(); - tsd_wrapper_t *wrapper = (tsd_wrapper_t *)TlsGetValue(tsd_tsd); - SetLastError(error); - - if (wrapper == NULL) { - return false; - } - - if (wrapper->initialized) { - wrapper->initialized = false; - tsd_cleanup(&wrapper->val); - if (wrapper->initialized) { - /* Trigger another cleanup round. */ - return true; - } - } - malloc_tsd_dalloc(wrapper); - return false; -} - -JEMALLOC_ALWAYS_INLINE void -tsd_wrapper_set(tsd_wrapper_t *wrapper) { - if (!TlsSetValue(tsd_tsd, (void *)wrapper)) { - malloc_write("<jemalloc>: Error setting TSD\n"); - abort(); - } -} - -JEMALLOC_ALWAYS_INLINE tsd_wrapper_t * -tsd_wrapper_get(bool init) { - DWORD error = GetLastError(); - tsd_wrapper_t *wrapper = (tsd_wrapper_t *) TlsGetValue(tsd_tsd); - SetLastError(error); - - if (init && unlikely(wrapper == NULL)) { - wrapper = (tsd_wrapper_t *) - malloc_tsd_malloc(sizeof(tsd_wrapper_t)); - if (wrapper == NULL) { - malloc_write("<jemalloc>: Error allocating TSD\n"); - abort(); - } else { - wrapper->initialized = false; - /* MSVC is finicky about aggregate initialization. */ - tsd_t tsd_initializer = TSD_INITIALIZER; - wrapper->val = tsd_initializer; - } - tsd_wrapper_set(wrapper); - } - return wrapper; -} - -JEMALLOC_ALWAYS_INLINE bool -tsd_boot0(void) { - tsd_tsd = TlsAlloc(); - if (tsd_tsd == TLS_OUT_OF_INDEXES) { - return true; - } - malloc_tsd_cleanup_register(&tsd_cleanup_wrapper); - tsd_wrapper_set(&tsd_boot_wrapper); - tsd_booted = true; - return false; -} - -JEMALLOC_ALWAYS_INLINE void -tsd_boot1(void) { - tsd_wrapper_t *wrapper; - wrapper = (tsd_wrapper_t *) - malloc_tsd_malloc(sizeof(tsd_wrapper_t)); - if (wrapper == NULL) { - malloc_write("<jemalloc>: Error allocating TSD\n"); - abort(); - } - tsd_boot_wrapper.initialized = false; - tsd_cleanup(&tsd_boot_wrapper.val); - wrapper->initialized = false; - tsd_t initializer = TSD_INITIALIZER; - wrapper->val = initializer; - tsd_wrapper_set(wrapper); -} -JEMALLOC_ALWAYS_INLINE bool -tsd_boot(void) { - if (tsd_boot0()) { - return true; - } - tsd_boot1(); - return false; -} - -JEMALLOC_ALWAYS_INLINE bool -tsd_booted_get(void) { - return tsd_booted; -} - -JEMALLOC_ALWAYS_INLINE bool -tsd_get_allocates(void) { - return true; -} - -/* Get/set. */ -JEMALLOC_ALWAYS_INLINE tsd_t * -tsd_get(bool init) { - tsd_wrapper_t *wrapper; - - assert(tsd_booted); - wrapper = tsd_wrapper_get(init); - if (tsd_get_allocates() && !init && wrapper == NULL) { - return NULL; - } - return &wrapper->val; -} - -JEMALLOC_ALWAYS_INLINE void -tsd_set(tsd_t *val) { - tsd_wrapper_t *wrapper; - - assert(tsd_booted); - wrapper = tsd_wrapper_get(true); - if (likely(&wrapper->val != val)) { - wrapper->val = *(val); - } - wrapper->initialized = true; -} ->>>>>>> main diff --git a/contrib/jemalloc/include/jemalloc/jemalloc_defs.h.in b/contrib/jemalloc/include/jemalloc/jemalloc_defs.h.in index 19c990dcdbdf..cbe2fca6ba53 100644 --- a/contrib/jemalloc/include/jemalloc/jemalloc_defs.h.in +++ b/contrib/jemalloc/include/jemalloc/jemalloc_defs.h.in @@ -1,4 +1,3 @@ -<<<<<<< HEAD /* Defined if __attribute__((...)) syntax is supported. */ #undef JEMALLOC_HAVE_ATTR @@ -53,54 +52,3 @@ /* sizeof(void *) == 2^LG_SIZEOF_PTR. */ #undef LG_SIZEOF_PTR -||||||| dec341af7695 -======= -/* Defined if __attribute__((...)) syntax is supported. */ -#undef JEMALLOC_HAVE_ATTR - -/* Defined if alloc_size attribute is supported. */ -#undef JEMALLOC_HAVE_ATTR_ALLOC_SIZE - -/* Defined if format_arg(...) attribute is supported. */ -#undef JEMALLOC_HAVE_ATTR_FORMAT_ARG - -/* Defined if format(gnu_printf, ...) attribute is supported. */ -#undef JEMALLOC_HAVE_ATTR_FORMAT_GNU_PRINTF - -/* Defined if format(printf, ...) attribute is supported. */ -#undef JEMALLOC_HAVE_ATTR_FORMAT_PRINTF - -/* - * Define overrides for non-standard allocator-related functions if they are - * present on the system. - */ -#undef JEMALLOC_OVERRIDE_MEMALIGN -#undef JEMALLOC_OVERRIDE_VALLOC - -/* - * At least Linux omits the "const" in: - * - * size_t malloc_usable_size(const void *ptr); - * - * Match the operating system's prototype. - */ -#undef JEMALLOC_USABLE_SIZE_CONST - -/* - * If defined, specify throw() for the public function prototypes when compiling - * with C++. The only justification for this is to match the prototypes that - * glibc defines. - */ -#undef JEMALLOC_USE_CXX_THROW - -#ifdef _MSC_VER -# ifdef _WIN64 -# define LG_SIZEOF_PTR_WIN 3 -# else -# define LG_SIZEOF_PTR_WIN 2 -# endif -#endif - -/* sizeof(void *) == 2^LG_SIZEOF_PTR. */ -#undef LG_SIZEOF_PTR ->>>>>>> main diff --git a/contrib/jemalloc/include/jemalloc/jemalloc_macros.h.in b/contrib/jemalloc/include/jemalloc/jemalloc_macros.h.in index dc57f521f580..ebb3137e6f7e 100644 --- a/contrib/jemalloc/include/jemalloc/jemalloc_macros.h.in +++ b/contrib/jemalloc/include/jemalloc/jemalloc_macros.h.in @@ -1,4 +1,3 @@ -<<<<<<< HEAD #include <stdlib.h> #include <stdbool.h> #include <stdint.h> @@ -148,135 +147,3 @@ #else # define JEMALLOC_SYS_NOTHROW JEMALLOC_NOTHROW #endif -||||||| dec341af7695 -======= -#include <stdlib.h> -#include <stdbool.h> -#include <stdint.h> -#include <limits.h> -#include <strings.h> - -#define JEMALLOC_VERSION "@jemalloc_version@" -#define JEMALLOC_VERSION_MAJOR @jemalloc_version_major@ -#define JEMALLOC_VERSION_MINOR @jemalloc_version_minor@ -#define JEMALLOC_VERSION_BUGFIX @jemalloc_version_bugfix@ -#define JEMALLOC_VERSION_NREV @jemalloc_version_nrev@ -#define JEMALLOC_VERSION_GID "@jemalloc_version_gid@" -#define JEMALLOC_VERSION_GID_IDENT @jemalloc_version_gid@ - -#define MALLOCX_LG_ALIGN(la) ((int)(la)) -#if LG_SIZEOF_PTR == 2 -# define MALLOCX_ALIGN(a) ((int)(ffs((int)(a))-1)) -#else -# define MALLOCX_ALIGN(a) \ - ((int)(((size_t)(a) < (size_t)INT_MAX) ? ffs((int)(a))-1 : \ - ffs((int)(((size_t)(a))>>32))+31)) -#endif -#define MALLOCX_ZERO ((int)0x40) -/* - * Bias tcache index bits so that 0 encodes "automatic tcache management", and 1 - * encodes MALLOCX_TCACHE_NONE. - */ -#define MALLOCX_TCACHE(tc) ((int)(((tc)+2) << 8)) -#define MALLOCX_TCACHE_NONE MALLOCX_TCACHE(-1) -/* - * Bias arena index bits so that 0 encodes "use an automatically chosen arena". - */ -#define MALLOCX_ARENA(a) ((((int)(a))+1) << 20) - -/* - * Use as arena index in "arena.<i>.{purge,decay,dss}" and - * "stats.arenas.<i>.*" mallctl interfaces to select all arenas. This - * definition is intentionally specified in raw decimal format to support - * cpp-based string concatenation, e.g. - * - * #define STRINGIFY_HELPER(x) #x - * #define STRINGIFY(x) STRINGIFY_HELPER(x) - * - * mallctl("arena." STRINGIFY(MALLCTL_ARENAS_ALL) ".purge", NULL, NULL, NULL, - * 0); - */ -#define MALLCTL_ARENAS_ALL 4096 -/* - * Use as arena index in "stats.arenas.<i>.*" mallctl interfaces to select - * destroyed arenas. - */ -#define MALLCTL_ARENAS_DESTROYED 4097 - -#if defined(__cplusplus) && defined(JEMALLOC_USE_CXX_THROW) -# define JEMALLOC_CXX_THROW throw() -#else -# define JEMALLOC_CXX_THROW -#endif - -#if defined(_MSC_VER) -# define JEMALLOC_ATTR(s) -# define JEMALLOC_ALIGNED(s) __declspec(align(s)) -# define JEMALLOC_ALLOC_SIZE(s) -# define JEMALLOC_ALLOC_SIZE2(s1, s2) -# ifndef JEMALLOC_EXPORT -# ifdef DLLEXPORT -# define JEMALLOC_EXPORT __declspec(dllexport) -# else -# define JEMALLOC_EXPORT __declspec(dllimport) -# endif -# endif -# define JEMALLOC_FORMAT_ARG(i) -# define JEMALLOC_FORMAT_PRINTF(s, i) -# define JEMALLOC_NOINLINE __declspec(noinline) -# ifdef __cplusplus -# define JEMALLOC_NOTHROW __declspec(nothrow) -# else -# define JEMALLOC_NOTHROW -# endif -# define JEMALLOC_SECTION(s) __declspec(allocate(s)) -# define JEMALLOC_RESTRICT_RETURN __declspec(restrict) -# if _MSC_VER >= 1900 && !defined(__EDG__) -# define JEMALLOC_ALLOCATOR __declspec(allocator) -# else -# define JEMALLOC_ALLOCATOR -# endif -#elif defined(JEMALLOC_HAVE_ATTR) -# define JEMALLOC_ATTR(s) __attribute__((s)) -# define JEMALLOC_ALIGNED(s) JEMALLOC_ATTR(aligned(s)) -# ifdef JEMALLOC_HAVE_ATTR_ALLOC_SIZE -# define JEMALLOC_ALLOC_SIZE(s) JEMALLOC_ATTR(alloc_size(s)) -# define JEMALLOC_ALLOC_SIZE2(s1, s2) JEMALLOC_ATTR(alloc_size(s1, s2)) -# else -# define JEMALLOC_ALLOC_SIZE(s) -# define JEMALLOC_ALLOC_SIZE2(s1, s2) -# endif -# ifndef JEMALLOC_EXPORT -# define JEMALLOC_EXPORT JEMALLOC_ATTR(visibility("default")) -# endif -# ifdef JEMALLOC_HAVE_ATTR_FORMAT_ARG -# define JEMALLOC_FORMAT_ARG(i) JEMALLOC_ATTR(__format_arg__(3)) -# else -# define JEMALLOC_FORMAT_ARG(i) -# endif -# ifdef JEMALLOC_HAVE_ATTR_FORMAT_GNU_PRINTF -# define JEMALLOC_FORMAT_PRINTF(s, i) JEMALLOC_ATTR(format(gnu_printf, s, i)) -# elif defined(JEMALLOC_HAVE_ATTR_FORMAT_PRINTF) -# define JEMALLOC_FORMAT_PRINTF(s, i) JEMALLOC_ATTR(format(printf, s, i)) -# else -# define JEMALLOC_FORMAT_PRINTF(s, i) -# endif -# define JEMALLOC_NOINLINE JEMALLOC_ATTR(noinline) -# define JEMALLOC_NOTHROW JEMALLOC_ATTR(nothrow) -# define JEMALLOC_SECTION(s) JEMALLOC_ATTR(section(s)) -# define JEMALLOC_RESTRICT_RETURN -# define JEMALLOC_ALLOCATOR -#else -# define JEMALLOC_ATTR(s) -# define JEMALLOC_ALIGNED(s) -# define JEMALLOC_ALLOC_SIZE(s) -# define JEMALLOC_ALLOC_SIZE2(s1, s2) -# define JEMALLOC_EXPORT -# define JEMALLOC_FORMAT_PRINTF(s, i) -# define JEMALLOC_NOINLINE -# define JEMALLOC_NOTHROW -# define JEMALLOC_SECTION(s) -# define JEMALLOC_RESTRICT_RETURN -# define JEMALLOC_ALLOCATOR -#endif ->>>>>>> main diff --git a/contrib/jemalloc/include/jemalloc/jemalloc_protos.h.in b/contrib/jemalloc/include/jemalloc/jemalloc_protos.h.in index 116ef116b4e1..356221cc8d52 100644 --- a/contrib/jemalloc/include/jemalloc/jemalloc_protos.h.in +++ b/contrib/jemalloc/include/jemalloc/jemalloc_protos.h.in @@ -1,4 +1,3 @@ -<<<<<<< HEAD /* * The @je_@ prefix on the following public symbol declarations is an artifact * of namespace management, and should be omitted in application code unless @@ -70,72 +69,3 @@ JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN void JEMALLOC_SYS_NOTHROW *@je_@valloc(size_t size) JEMALLOC_CXX_THROW JEMALLOC_ATTR(malloc); #endif -||||||| dec341af7695 -======= -/* - * The @je_@ prefix on the following public symbol declarations is an artifact - * of namespace management, and should be omitted in application code unless - * JEMALLOC_NO_DEMANGLE is defined (see jemalloc_mangle@install_suffix@.h). - */ -extern JEMALLOC_EXPORT const char *@je_@malloc_conf; -extern JEMALLOC_EXPORT void (*@je_@malloc_message)(void *cbopaque, - const char *s); - -JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN - void JEMALLOC_NOTHROW *@je_@malloc(size_t size) - JEMALLOC_CXX_THROW JEMALLOC_ATTR(malloc) JEMALLOC_ALLOC_SIZE(1); -JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN - void JEMALLOC_NOTHROW *@je_@calloc(size_t num, size_t size) - JEMALLOC_CXX_THROW JEMALLOC_ATTR(malloc) JEMALLOC_ALLOC_SIZE2(1, 2); -JEMALLOC_EXPORT int JEMALLOC_NOTHROW @je_@posix_memalign(void **memptr, - size_t alignment, size_t size) JEMALLOC_CXX_THROW JEMALLOC_ATTR(nonnull(1)); -JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN - void JEMALLOC_NOTHROW *@je_@aligned_alloc(size_t alignment, - size_t size) JEMALLOC_CXX_THROW JEMALLOC_ATTR(malloc) - JEMALLOC_ALLOC_SIZE(2); -JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN - void JEMALLOC_NOTHROW *@je_@realloc(void *ptr, size_t size) - JEMALLOC_CXX_THROW JEMALLOC_ALLOC_SIZE(2); -JEMALLOC_EXPORT void JEMALLOC_NOTHROW @je_@free(void *ptr) - JEMALLOC_CXX_THROW; - -JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN - void JEMALLOC_NOTHROW *@je_@mallocx(size_t size, int flags) - JEMALLOC_ATTR(malloc) JEMALLOC_ALLOC_SIZE(1); -JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN - void JEMALLOC_NOTHROW *@je_@rallocx(void *ptr, size_t size, - int flags) JEMALLOC_ALLOC_SIZE(2); -JEMALLOC_EXPORT size_t JEMALLOC_NOTHROW @je_@xallocx(void *ptr, size_t size, - size_t extra, int flags); -JEMALLOC_EXPORT size_t JEMALLOC_NOTHROW @je_@sallocx(const void *ptr, - int flags) JEMALLOC_ATTR(pure); -JEMALLOC_EXPORT void JEMALLOC_NOTHROW @je_@dallocx(void *ptr, int flags); -JEMALLOC_EXPORT void JEMALLOC_NOTHROW @je_@sdallocx(void *ptr, size_t size, - int flags); -JEMALLOC_EXPORT size_t JEMALLOC_NOTHROW @je_@nallocx(size_t size, int flags) - JEMALLOC_ATTR(pure); - -JEMALLOC_EXPORT int JEMALLOC_NOTHROW @je_@mallctl(const char *name, - void *oldp, size_t *oldlenp, void *newp, size_t newlen); -JEMALLOC_EXPORT int JEMALLOC_NOTHROW @je_@mallctlnametomib(const char *name, - size_t *mibp, size_t *miblenp); -JEMALLOC_EXPORT int JEMALLOC_NOTHROW @je_@mallctlbymib(const size_t *mib, - size_t miblen, void *oldp, size_t *oldlenp, void *newp, size_t newlen); -JEMALLOC_EXPORT void JEMALLOC_NOTHROW @je_@malloc_stats_print( - void (*write_cb)(void *, const char *), void *@je_@cbopaque, - const char *opts); -JEMALLOC_EXPORT size_t JEMALLOC_NOTHROW @je_@malloc_usable_size( - JEMALLOC_USABLE_SIZE_CONST void *ptr) JEMALLOC_CXX_THROW; - -#ifdef JEMALLOC_OVERRIDE_MEMALIGN -JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN - void JEMALLOC_NOTHROW *@je_@memalign(size_t alignment, size_t size) - JEMALLOC_CXX_THROW JEMALLOC_ATTR(malloc); -#endif - -#ifdef JEMALLOC_OVERRIDE_VALLOC -JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN - void JEMALLOC_NOTHROW *@je_@valloc(size_t size) JEMALLOC_CXX_THROW - JEMALLOC_ATTR(malloc); -#endif ->>>>>>> main diff --git a/contrib/jemalloc/m4/ax_cxx_compile_stdcxx.m4 b/contrib/jemalloc/m4/ax_cxx_compile_stdcxx.m4 index 72784472d275..43087b2e6889 100644 --- a/contrib/jemalloc/m4/ax_cxx_compile_stdcxx.m4 +++ b/contrib/jemalloc/m4/ax_cxx_compile_stdcxx.m4 @@ -1,4 +1,3 @@ -<<<<<<< HEAD # =========================================================================== # https://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx.html # =========================================================================== @@ -950,568 +949,3 @@ namespace cxx17 #endif // __cplusplus < 201703L ]]) -||||||| dec341af7695 -======= -# =========================================================================== -# http://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx.html -# =========================================================================== -# -# SYNOPSIS -# -# AX_CXX_COMPILE_STDCXX(VERSION, [ext|noext], [mandatory|optional]) -# -# DESCRIPTION -# -# Check for baseline language coverage in the compiler for the specified -# version of the C++ standard. If necessary, add switches to CXX and -# CXXCPP to enable support. VERSION may be '11' (for the C++11 standard) -# or '14' (for the C++14 standard). -# -# The second argument, if specified, indicates whether you insist on an -# extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g. -# -std=c++11). If neither is specified, you get whatever works, with -# preference for an extended mode. -# -# The third argument, if specified 'mandatory' or if left unspecified, -# indicates that baseline support for the specified C++ standard is -# required and that the macro should error out if no mode with that -# support is found. If specified 'optional', then configuration proceeds -# regardless, after defining HAVE_CXX${VERSION} if and only if a -# supporting mode is found. -# -# LICENSE -# -# Copyright (c) 2008 Benjamin Kosnik <bkoz@redhat.com> -# Copyright (c) 2012 Zack Weinberg <zackw@panix.com> -# Copyright (c) 2013 Roy Stogner <roystgnr@ices.utexas.edu> -# Copyright (c) 2014, 2015 Google Inc.; contributed by Alexey Sokolov <sokolov@google.com> -# Copyright (c) 2015 Paul Norman <penorman@mac.com> -# Copyright (c) 2015 Moritz Klammler <moritz@klammler.eu> -# -# Copying and distribution of this file, with or without modification, are -# permitted in any medium without royalty provided the copyright notice -# and this notice are preserved. This file is offered as-is, without any -# warranty. - -#serial 4 - -dnl This macro is based on the code from the AX_CXX_COMPILE_STDCXX_11 macro -dnl (serial version number 13). - -AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl - m4_if([$1], [11], [], - [$1], [14], [], - [$1], [17], [m4_fatal([support for C++17 not yet implemented in AX_CXX_COMPILE_STDCXX])], - [m4_fatal([invalid first argument `$1' to AX_CXX_COMPILE_STDCXX])])dnl - m4_if([$2], [], [], - [$2], [ext], [], - [$2], [noext], [], - [m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX])])dnl - m4_if([$3], [], [ax_cxx_compile_cxx$1_required=true], - [$3], [mandatory], [ax_cxx_compile_cxx$1_required=true], - [$3], [optional], [ax_cxx_compile_cxx$1_required=false], - [m4_fatal([invalid third argument `$3' to AX_CXX_COMPILE_STDCXX])]) - AC_LANG_PUSH([C++])dnl - ac_success=no - AC_CACHE_CHECK(whether $CXX supports C++$1 features by default, - ax_cv_cxx_compile_cxx$1, - [AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], - [ax_cv_cxx_compile_cxx$1=yes], - [ax_cv_cxx_compile_cxx$1=no])]) - if test x$ax_cv_cxx_compile_cxx$1 = xyes; then - ac_success=yes - fi - - m4_if([$2], [noext], [], [dnl - if test x$ac_success = xno; then - for switch in -std=gnu++$1 -std=gnu++0x; do - cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch]) - AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch, - $cachevar, - [ac_save_CXX="$CXX" - CXX="$CXX $switch" - AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], - [eval $cachevar=yes], - [eval $cachevar=no]) - CXX="$ac_save_CXX"]) - if eval test x\$$cachevar = xyes; then - CXX="$CXX $switch" - if test -n "$CXXCPP" ; then - CXXCPP="$CXXCPP $switch" - fi - ac_success=yes - break - fi - done - fi]) - - m4_if([$2], [ext], [], [dnl - if test x$ac_success = xno; then - dnl HP's aCC needs +std=c++11 according to: - dnl http://h21007.www2.hp.com/portal/download/files/unprot/aCxx/PDF_Release_Notes/769149-001.pdf - dnl Cray's crayCC needs "-h std=c++11" - for switch in -std=c++$1 -std=c++0x +std=c++$1 "-h std=c++$1"; do - cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch]) - AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch, - $cachevar, - [ac_save_CXX="$CXX" - CXX="$CXX $switch" - AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], - [eval $cachevar=yes], - [eval $cachevar=no]) - CXX="$ac_save_CXX"]) - if eval test x\$$cachevar = xyes; then - CXX="$CXX $switch" - if test -n "$CXXCPP" ; then - CXXCPP="$CXXCPP $switch" - fi - ac_success=yes - break - fi - done - fi]) - AC_LANG_POP([C++]) - if test x$ax_cxx_compile_cxx$1_required = xtrue; then - if test x$ac_success = xno; then - AC_MSG_ERROR([*** A compiler with support for C++$1 language features is required.]) - fi - fi - if test x$ac_success = xno; then - HAVE_CXX$1=0 - AC_MSG_NOTICE([No compiler with C++$1 support was found]) - else - HAVE_CXX$1=1 - AC_DEFINE(HAVE_CXX$1,1, - [define if the compiler supports basic C++$1 syntax]) - fi - AC_SUBST(HAVE_CXX$1) -]) - - -dnl Test body for checking C++11 support - -m4_define([_AX_CXX_COMPILE_STDCXX_testbody_11], - _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 -) - - -dnl Test body for checking C++14 support - -m4_define([_AX_CXX_COMPILE_STDCXX_testbody_14], - _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 - _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 -) - - -dnl Tests for new features in C++11 - -m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_11], [[ - -// If the compiler admits that it is not ready for C++11, why torture it? -// Hopefully, this will speed up the test. - -#ifndef __cplusplus - -#error "This is not a C++ compiler" - -#elif __cplusplus < 201103L - -#error "This is not a C++11 compiler" - -#else - -namespace cxx11 -{ - - namespace test_static_assert - { - - template <typename T> - struct check - { - static_assert(sizeof(int) <= sizeof(T), "not big enough"); - }; - - } - - namespace test_final_override - { - - struct Base - { - virtual void f() {} - }; - - struct Derived : public Base - { - virtual void f() override {} - }; - - } - - namespace test_double_right_angle_brackets - { - - template < typename T > - struct check {}; - - typedef check<void> single_type; - typedef check<check<void>> double_type; - typedef check<check<check<void>>> triple_type; - typedef check<check<check<check<void>>>> quadruple_type; - - } - - namespace test_decltype - { - - int - f() - { - int a = 1; - decltype(a) b = 2; - return a + b; - } - - } - - namespace test_type_deduction - { - - template < typename T1, typename T2 > - struct is_same - { - static const bool value = false; - }; - - template < typename T > - struct is_same<T, T> - { - static const bool value = true; - }; - - template < typename T1, typename T2 > - auto - add(T1 a1, T2 a2) -> decltype(a1 + a2) - { - return a1 + a2; - } - - int - test(const int c, volatile int v) - { - static_assert(is_same<int, decltype(0)>::value == true, ""); - static_assert(is_same<int, decltype(c)>::value == false, ""); - static_assert(is_same<int, decltype(v)>::value == false, ""); - auto ac = c; - auto av = v; - auto sumi = ac + av + 'x'; - auto sumf = ac + av + 1.0; - static_assert(is_same<int, decltype(ac)>::value == true, ""); - static_assert(is_same<int, decltype(av)>::value == true, ""); - static_assert(is_same<int, decltype(sumi)>::value == true, ""); - static_assert(is_same<int, decltype(sumf)>::value == false, ""); - static_assert(is_same<int, decltype(add(c, v))>::value == true, ""); - return (sumf > 0.0) ? sumi : add(c, v); - } - - } - - namespace test_noexcept - { - - int f() { return 0; } - int g() noexcept { return 0; } - - static_assert(noexcept(f()) == false, ""); - static_assert(noexcept(g()) == true, ""); - - } - - namespace test_constexpr - { - - template < typename CharT > - unsigned long constexpr - strlen_c_r(const CharT *const s, const unsigned long acc) noexcept - { - return *s ? strlen_c_r(s + 1, acc + 1) : acc; - } - - template < typename CharT > - unsigned long constexpr - strlen_c(const CharT *const s) noexcept - { - return strlen_c_r(s, 0UL); - } - - static_assert(strlen_c("") == 0UL, ""); - static_assert(strlen_c("1") == 1UL, ""); - static_assert(strlen_c("example") == 7UL, ""); - static_assert(strlen_c("another\0example") == 7UL, ""); - - } - - namespace test_rvalue_references - { - - template < int N > - struct answer - { - static constexpr int value = N; - }; - - answer<1> f(int&) { return answer<1>(); } - answer<2> f(const int&) { return answer<2>(); } - answer<3> f(int&&) { return answer<3>(); } - - void - test() - { - int i = 0; - const int c = 0; - static_assert(decltype(f(i))::value == 1, ""); - static_assert(decltype(f(c))::value == 2, ""); - static_assert(decltype(f(0))::value == 3, ""); - } - - } - - namespace test_uniform_initialization - { - - struct test - { - static const int zero {}; - static const int one {1}; - }; - - static_assert(test::zero == 0, ""); - static_assert(test::one == 1, ""); - - } - - namespace test_lambdas - { - - void - test1() - { - auto lambda1 = [](){}; - auto lambda2 = lambda1; - lambda1(); - lambda2(); - } - - int - test2() - { - auto a = [](int i, int j){ return i + j; }(1, 2); - auto b = []() -> int { return '0'; }(); - auto c = [=](){ return a + b; }(); - auto d = [&](){ return c; }(); - auto e = [a, &b](int x) mutable { - const auto identity = [](int y){ return y; }; - for (auto i = 0; i < a; ++i) - a += b--; - return x + identity(a + b); - }(0); - return a + b + c + d + e; - } - - int - test3() - { - const auto nullary = [](){ return 0; }; - const auto unary = [](int x){ return x; }; - using nullary_t = decltype(nullary); - using unary_t = decltype(unary); - const auto higher1st = [](nullary_t f){ return f(); }; - const auto higher2nd = [unary](nullary_t f1){ - return [unary, f1](unary_t f2){ return f2(unary(f1())); }; - }; - return higher1st(nullary) + higher2nd(nullary)(unary); - } - - } - - namespace test_variadic_templates - { - - template <int...> - struct sum; - - template <int N0, int... N1toN> - struct sum<N0, N1toN...> - { - static constexpr auto value = N0 + sum<N1toN...>::value; - }; - - template <> - struct sum<> - { - static constexpr auto value = 0; - }; - - static_assert(sum<>::value == 0, ""); - static_assert(sum<1>::value == 1, ""); - static_assert(sum<23>::value == 23, ""); - static_assert(sum<1, 2>::value == 3, ""); - static_assert(sum<5, 5, 11>::value == 21, ""); - static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, ""); - - } - - // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae - // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function - // because of this. - namespace test_template_alias_sfinae - { - - struct foo {}; - - template<typename T> - using member = typename T::member_type; - - template<typename T> - void func(...) {} - - template<typename T> - void func(member<T>*) {} - - void test(); - - void test() { func<foo>(0); } - - } - -} // namespace cxx11 - -#endif // __cplusplus >= 201103L - -]]) - - -dnl Tests for new features in C++14 - -m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_14], [[ - -// If the compiler admits that it is not ready for C++14, why torture it? -// Hopefully, this will speed up the test. - -#ifndef __cplusplus - -#error "This is not a C++ compiler" - -#elif __cplusplus < 201402L - -#error "This is not a C++14 compiler" - -#else - -namespace cxx14 -{ - - namespace test_polymorphic_lambdas - { - - int - test() - { - const auto lambda = [](auto&&... args){ - const auto istiny = [](auto x){ - return (sizeof(x) == 1UL) ? 1 : 0; - }; - const int aretiny[] = { istiny(args)... }; - return aretiny[0]; - }; - return lambda(1, 1L, 1.0f, '1'); - } - - } - - namespace test_binary_literals - { - - constexpr auto ivii = 0b0000000000101010; - static_assert(ivii == 42, "wrong value"); - - } - - namespace test_generalized_constexpr - { - - template < typename CharT > - constexpr unsigned long - strlen_c(const CharT *const s) noexcept - { - auto length = 0UL; - for (auto p = s; *p; ++p) - ++length; - return length; - } - - static_assert(strlen_c("") == 0UL, ""); - static_assert(strlen_c("x") == 1UL, ""); - static_assert(strlen_c("test") == 4UL, ""); - static_assert(strlen_c("another\0test") == 7UL, ""); - - } - - namespace test_lambda_init_capture - { - - int - test() - { - auto x = 0; - const auto lambda1 = [a = x](int b){ return a + b; }; - const auto lambda2 = [a = lambda1(x)](){ return a; }; - return lambda2(); - } - - } - - namespace test_digit_seperators - { - - constexpr auto ten_million = 100'000'000; - static_assert(ten_million == 100000000, ""); - - } - - namespace test_return_type_deduction - { - - auto f(int& x) { return x; } - decltype(auto) g(int& x) { return x; } - - template < typename T1, typename T2 > - struct is_same - { - static constexpr auto value = false; - }; - - template < typename T > - struct is_same<T, T> - { - static constexpr auto value = true; - }; - - int - test() - { - auto x = 0; - static_assert(is_same<int, decltype(f(x))>::value, ""); - static_assert(is_same<int&, decltype(g(x))>::value, ""); - return x; - } - - } - -} // namespace cxx14 - -#endif // __cplusplus >= 201402L - -]]) ->>>>>>> main diff --git a/contrib/jemalloc/scripts/gen_run_tests.py b/contrib/jemalloc/scripts/gen_run_tests.py index 698d3bce4bbf..7c3075f9f6a6 100755 --- a/contrib/jemalloc/scripts/gen_run_tests.py +++ b/contrib/jemalloc/scripts/gen_run_tests.py @@ -1,4 +1,3 @@ -<<<<<<< HEAD #!/usr/bin/env python3 import sys @@ -129,132 +128,3 @@ chmod 755 run_test_%(ind)d.sh""" % {'ind': ind, 'config_line': config_line, print('for i in `seq 0 %(last_ind)d` ; do echo run_test_${i}.sh ; done | xargs' ' -P %(nparallel)d -n 1 sh' % {'last_ind': ind-1, 'nparallel': nparallel}) -||||||| dec341af7695 -======= -#!/usr/bin/env python - -import sys -from itertools import combinations -from os import uname -from multiprocessing import cpu_count -from subprocess import call - -# Later, we want to test extended vaddr support. Apparently, the "real" way of -# checking this is flaky on OS X. -bits_64 = sys.maxsize > 2**32 - -nparallel = cpu_count() * 2 - -uname = uname()[0] - -if "BSD" in uname: - make_cmd = 'gmake' -else: - make_cmd = 'make' - -def powerset(items): - result = [] - for i in xrange(len(items) + 1): - result += combinations(items, i) - return result - -possible_compilers = [] -for cc, cxx in (['gcc', 'g++'], ['clang', 'clang++']): - try: - cmd_ret = call([cc, "-v"]) - if cmd_ret == 0: - possible_compilers.append((cc, cxx)) - except: - pass -possible_compiler_opts = [ - '-m32', -] -possible_config_opts = [ - '--enable-debug', - '--enable-prof', - '--disable-stats', - '--enable-opt-safety-checks', -] -if bits_64: - possible_config_opts.append('--with-lg-vaddr=56') - -possible_malloc_conf_opts = [ - 'tcache:false', - 'dss:primary', - 'percpu_arena:percpu', - 'background_thread:true', -] - -print 'set -e' -print 'if [ -f Makefile ] ; then %(make_cmd)s relclean ; fi' % {'make_cmd': make_cmd} -print 'autoconf' -print 'rm -rf run_tests.out' -print 'mkdir run_tests.out' -print 'cd run_tests.out' - -ind = 0 -for cc, cxx in possible_compilers: - for compiler_opts in powerset(possible_compiler_opts): - for config_opts in powerset(possible_config_opts): - for malloc_conf_opts in powerset(possible_malloc_conf_opts): - if cc is 'clang' \ - and '-m32' in possible_compiler_opts \ - and '--enable-prof' in config_opts: - continue - config_line = ( - 'EXTRA_CFLAGS=-Werror EXTRA_CXXFLAGS=-Werror ' - + 'CC="{} {}" '.format(cc, " ".join(compiler_opts)) - + 'CXX="{} {}" '.format(cxx, " ".join(compiler_opts)) - + '../../configure ' - + " ".join(config_opts) + (' --with-malloc-conf=' + - ",".join(malloc_conf_opts) if len(malloc_conf_opts) > 0 - else '') - ) - - # We don't want to test large vaddr spaces in 32-bit mode. - if ('-m32' in compiler_opts and '--with-lg-vaddr=56' in - config_opts): - continue - - # Per CPU arenas are only supported on Linux. - linux_supported = ('percpu_arena:percpu' in malloc_conf_opts \ - or 'background_thread:true' in malloc_conf_opts) - # Heap profiling and dss are not supported on OS X. - darwin_unsupported = ('--enable-prof' in config_opts or \ - 'dss:primary' in malloc_conf_opts) - if (uname == 'Linux' and linux_supported) \ - or (not linux_supported and (uname != 'Darwin' or \ - not darwin_unsupported)): - print """cat <<EOF > run_test_%(ind)d.sh -#!/bin/sh - -set -e - -abort() { - echo "==> Error" >> run_test.log - echo "Error; see run_tests.out/run_test_%(ind)d.out/run_test.log" - exit 255 # Special exit code tells xargs to terminate. -} - -# Environment variables are not supported. -run_cmd() { - echo "==> \$@" >> run_test.log - \$@ >> run_test.log 2>&1 || abort -} - -echo "=> run_test_%(ind)d: %(config_line)s" -mkdir run_test_%(ind)d.out -cd run_test_%(ind)d.out - -echo "==> %(config_line)s" >> run_test.log -%(config_line)s >> run_test.log 2>&1 || abort - -run_cmd %(make_cmd)s all tests -run_cmd %(make_cmd)s check -run_cmd %(make_cmd)s distclean -EOF -chmod 755 run_test_%(ind)d.sh""" % {'ind': ind, 'config_line': config_line, 'make_cmd': make_cmd} - ind += 1 - -print 'for i in `seq 0 %(last_ind)d` ; do echo run_test_${i}.sh ; done | xargs -P %(nparallel)d -n 1 sh' % {'last_ind': ind-1, 'nparallel': nparallel} ->>>>>>> main diff --git a/contrib/jemalloc/scripts/gen_travis.py b/contrib/jemalloc/scripts/gen_travis.py index c306744e6a65..4366a066eeab 100755 --- a/contrib/jemalloc/scripts/gen_travis.py +++ b/contrib/jemalloc/scripts/gen_travis.py @@ -1,4 +1,3 @@ -<<<<<<< HEAD #!/usr/bin/env python3 from itertools import combinations, chain @@ -326,155 +325,3 @@ def main(): if __name__ == '__main__': main() -||||||| dec341af7695 -======= -#!/usr/bin/env python - -from itertools import combinations - -travis_template = """\ -language: generic -dist: precise - -matrix: - include: -%s - -before_script: - - autoconf - - scripts/gen_travis.py > travis_script && diff .travis.yml travis_script - - ./configure ${COMPILER_FLAGS:+ \ - CC="$CC $COMPILER_FLAGS" \ - CXX="$CXX $COMPILER_FLAGS" } \ - $CONFIGURE_FLAGS - - make -j3 - - make -j3 tests - -script: - - make check -""" - -# The 'default' configuration is gcc, on linux, with no compiler or configure -# flags. We also test with clang, -m32, --enable-debug, --enable-prof, -# --disable-stats, and --with-malloc-conf=tcache:false. To avoid abusing -# travis though, we don't test all 2**7 = 128 possible combinations of these; -# instead, we only test combinations of up to 2 'unusual' settings, under the -# hope that bugs involving interactions of such settings are rare. -# Things at once, for C(7, 0) + C(7, 1) + C(7, 2) = 29 -MAX_UNUSUAL_OPTIONS = 2 - -os_default = 'linux' -os_unusual = 'osx' - -compilers_default = 'CC=gcc CXX=g++' -compilers_unusual = 'CC=clang CXX=clang++' - -compiler_flag_unusuals = ['-m32'] - -configure_flag_unusuals = [ - '--enable-debug', - '--enable-prof', - '--disable-stats', - '--disable-libdl', - '--enable-opt-safety-checks', -] - -malloc_conf_unusuals = [ - 'tcache:false', - 'dss:primary', - 'percpu_arena:percpu', - 'background_thread:true', -] - -all_unusuals = ( - [os_unusual] + [compilers_unusual] + compiler_flag_unusuals - + configure_flag_unusuals + malloc_conf_unusuals -) - -unusual_combinations_to_test = [] -for i in xrange(MAX_UNUSUAL_OPTIONS + 1): - unusual_combinations_to_test += combinations(all_unusuals, i) - -gcc_multilib_set = False -# Formats a job from a combination of flags -def format_job(combination): - global gcc_multilib_set - - os = os_unusual if os_unusual in combination else os_default - compilers = compilers_unusual if compilers_unusual in combination else compilers_default - - compiler_flags = [x for x in combination if x in compiler_flag_unusuals] - configure_flags = [x for x in combination if x in configure_flag_unusuals] - malloc_conf = [x for x in combination if x in malloc_conf_unusuals] - - # Filter out unsupported configurations on OS X. - if os == 'osx' and ('dss:primary' in malloc_conf or \ - 'percpu_arena:percpu' in malloc_conf or 'background_thread:true' \ - in malloc_conf): - return "" - if len(malloc_conf) > 0: - configure_flags.append('--with-malloc-conf=' + ",".join(malloc_conf)) - - # Filter out an unsupported configuration - heap profiling on OS X. - if os == 'osx' and '--enable-prof' in configure_flags: - return "" - - # We get some spurious errors when -Warray-bounds is enabled. - env_string = ('{} COMPILER_FLAGS="{}" CONFIGURE_FLAGS="{}" ' - 'EXTRA_CFLAGS="-Werror -Wno-array-bounds"').format( - compilers, " ".join(compiler_flags), " ".join(configure_flags)) - - job = "" - job += ' - os: %s\n' % os - job += ' env: %s\n' % env_string - if '-m32' in combination and os == 'linux': - job += ' addons:' - if gcc_multilib_set: - job += ' *gcc_multilib\n' - else: - job += ' &gcc_multilib\n' - job += ' apt:\n' - job += ' packages:\n' - job += ' - gcc-multilib\n' - gcc_multilib_set = True - return job - -include_rows = "" -for combination in unusual_combinations_to_test: - include_rows += format_job(combination) - -# Development build -include_rows += '''\ - # Development build - - os: linux - env: CC=gcc CXX=g++ COMPILER_FLAGS="" CONFIGURE_FLAGS="--enable-debug --disable-cache-oblivious --enable-stats --enable-log --enable-prof" EXTRA_CFLAGS="-Werror -Wno-array-bounds" -''' - -# Enable-expermental-smallocx -include_rows += '''\ - # --enable-expermental-smallocx: - - os: linux - env: CC=gcc CXX=g++ COMPILER_FLAGS="" CONFIGURE_FLAGS="--enable-debug --enable-experimental-smallocx --enable-stats --enable-prof" EXTRA_CFLAGS="-Werror -Wno-array-bounds" -''' - -# Valgrind build bots -include_rows += ''' - # Valgrind - - os: linux - env: CC=gcc CXX=g++ COMPILER_FLAGS="" CONFIGURE_FLAGS="" EXTRA_CFLAGS="-Werror -Wno-array-bounds" JEMALLOC_TEST_PREFIX="valgrind" - addons: - apt: - packages: - - valgrind -''' - -# To enable valgrind on macosx add: -# -# - os: osx -# env: CC=gcc CXX=g++ COMPILER_FLAGS="" CONFIGURE_FLAGS="" EXTRA_CFLAGS="-Werror -Wno-array-bounds" JEMALLOC_TEST_PREFIX="valgrind" -# install: brew install valgrind -# -# It currently fails due to: https://github.com/jemalloc/jemalloc/issues/1274 - -print travis_template % include_rows ->>>>>>> main diff --git a/contrib/jemalloc/src/jemalloc_cpp.cpp b/contrib/jemalloc/src/jemalloc_cpp.cpp index d606686e0c97..451655f1b5a5 100644 --- a/contrib/jemalloc/src/jemalloc_cpp.cpp +++ b/contrib/jemalloc/src/jemalloc_cpp.cpp @@ -1,4 +1,3 @@ -<<<<<<< HEAD #include <mutex> #include <new> @@ -253,147 +252,3 @@ operator delete[](void* ptr, std::size_t size, std::align_val_t alignment) noexc } #endif // __cpp_aligned_new -||||||| dec341af7695 -======= -#include <mutex> -#include <new> - -#define JEMALLOC_CPP_CPP_ -#ifdef __cplusplus -extern "C" { -#endif - -#include "jemalloc/internal/jemalloc_preamble.h" -#include "jemalloc/internal/jemalloc_internal_includes.h" - -#ifdef __cplusplus -} -#endif - -// All operators in this file are exported. - -// Possibly alias hidden versions of malloc and sdallocx to avoid an extra plt -// thunk? -// -// extern __typeof (sdallocx) sdallocx_int -// __attribute ((alias ("sdallocx"), -// visibility ("hidden"))); -// -// ... but it needs to work with jemalloc namespaces. - -void *operator new(std::size_t size); -void *operator new[](std::size_t size); -void *operator new(std::size_t size, const std::nothrow_t &) noexcept; -void *operator new[](std::size_t size, const std::nothrow_t &) noexcept; -void operator delete(void *ptr) noexcept; -void operator delete[](void *ptr) noexcept; -void operator delete(void *ptr, const std::nothrow_t &) noexcept; -void operator delete[](void *ptr, const std::nothrow_t &) noexcept; - -#if __cpp_sized_deallocation >= 201309 -/* C++14's sized-delete operators. */ -void operator delete(void *ptr, std::size_t size) noexcept; -void operator delete[](void *ptr, std::size_t size) noexcept; -#endif - -JEMALLOC_NOINLINE -static void * -handleOOM(std::size_t size, bool nothrow) { - void *ptr = nullptr; - - while (ptr == nullptr) { - std::new_handler handler; - // GCC-4.8 and clang 4.0 do not have std::get_new_handler. - { - static std::mutex mtx; - std::lock_guard<std::mutex> lock(mtx); - - handler = std::set_new_handler(nullptr); - std::set_new_handler(handler); - } - if (handler == nullptr) - break; - - try { - handler(); - } catch (const std::bad_alloc &) { - break; - } - - ptr = je_malloc(size); - } - - if (ptr == nullptr && !nothrow) - std::__throw_bad_alloc(); - return ptr; -} - -template <bool IsNoExcept> -JEMALLOC_ALWAYS_INLINE -void * -newImpl(std::size_t size) noexcept(IsNoExcept) { - void *ptr = je_malloc(size); - if (likely(ptr != nullptr)) - return ptr; - - return handleOOM(size, IsNoExcept); -} - -void * -operator new(std::size_t size) { - return newImpl<false>(size); -} - -void * -operator new[](std::size_t size) { - return newImpl<false>(size); -} - -void * -operator new(std::size_t size, const std::nothrow_t &) noexcept { - return newImpl<true>(size); -} - -void * -operator new[](std::size_t size, const std::nothrow_t &) noexcept { - return newImpl<true>(size); -} - -void -operator delete(void *ptr) noexcept { - je_free(ptr); -} - -void -operator delete[](void *ptr) noexcept { - je_free(ptr); -} - -void -operator delete(void *ptr, const std::nothrow_t &) noexcept { - je_free(ptr); -} - -void operator delete[](void *ptr, const std::nothrow_t &) noexcept { - je_free(ptr); -} - -#if __cpp_sized_deallocation >= 201309 - -void -operator delete(void *ptr, std::size_t size) noexcept { - if (unlikely(ptr == nullptr)) { - return; - } - je_sdallocx_noflags(ptr, size); -} - -void operator delete[](void *ptr, std::size_t size) noexcept { - if (unlikely(ptr == nullptr)) { - return; - } - je_sdallocx_noflags(ptr, size); -} - -#endif // __cpp_sized_deallocation ->>>>>>> main diff --git a/contrib/tzcode/localtime.c b/contrib/tzcode/localtime.c index a80d422f2955..15afeeecb6d0 100644 --- a/contrib/tzcode/localtime.c +++ b/contrib/tzcode/localtime.c @@ -615,6 +615,7 @@ tzloadbody(char const *name, struct state *sp, char tzloadflags, name = TZDEFAULT; if (! name) return EINVAL; + tzloadflags &= ~TZLOAD_FROMENV; } if (name[0] == ':') @@ -670,11 +671,13 @@ tzloadbody(char const *name, struct state *sp, char tzloadflags, fid = _open(name, (O_RDONLY | O_BINARY | O_CLOEXEC | O_CLOFORK | O_IGNORE_CTTY | O_NOCTTY)); #else /* __FreeBSD__ */ + if ((tzloadflags & TZLOAD_FROMENV) && strcmp(name, TZDEFAULT) == 0) + tzloadflags &= ~TZLOAD_FROMENV; relname = name; if (strncmp(relname, TZDIR "/", strlen(TZDIR) + 1) == 0) relname += strlen(TZDIR) + 1; dd = _open(TZDIR, O_DIRECTORY | O_RDONLY); - if (issetugid() && (tzloadflags & TZLOAD_FROMENV)) { + if ((tzloadflags & TZLOAD_FROMENV) && issetugid()) { if (dd < 0) return errno; if (fstatat(dd, name, &sb, AT_RESOLVE_BENEATH) < 0) { @@ -1624,14 +1627,13 @@ zoneinit(struct state *sp, char const *name, char tzloadflags) static void tzset_unlocked(void) { + char const *name = getenv("TZ"); #ifdef __FreeBSD__ - tzset_unlocked_name(getenv("TZ")); + tzset_unlocked_name(name); } static void tzset_unlocked_name(char const *name) { -#else - char const *name = getenv("TZ"); #endif struct state *sp = lclptr; int lcl = name ? strlen(name) < sizeof lcl_TZname : -1; diff --git a/lib/libc/tests/stdtime/detect_tz_changes_test.c b/lib/libc/tests/stdtime/detect_tz_changes_test.c index ad8c4818669d..6648d8498cc5 100644 --- a/lib/libc/tests/stdtime/detect_tz_changes_test.c +++ b/lib/libc/tests/stdtime/detect_tz_changes_test.c @@ -70,7 +70,7 @@ change_tz(const char *tzn) ATF_REQUIRE((zfd = open(zfn, O_DIRECTORY | O_SEARCH)) >= 0); ATF_REQUIRE((sfd = openat(zfd, tzn, O_RDONLY)) >= 0); - ATF_REQUIRE((dfd = open(tfn, O_CREAT | O_TRUNC | O_WRONLY)) >= 0); + ATF_REQUIRE((dfd = open(tfn, O_CREAT | O_TRUNC | O_WRONLY, 0644)) >= 0); do { clen = copy_file_range(sfd, NULL, dfd, NULL, SSIZE_MAX, 0); ATF_REQUIRE_MSG(clen != -1, "failed to copy %s/%s: %m", @@ -83,6 +83,19 @@ change_tz(const char *tzn) debug("time zone %s installed", tzn); } +static void +test_tz(const char *expect) +{ + char buf[128]; + struct tm *tm; + size_t len; + + ATF_REQUIRE((tm = localtime(&then)) != NULL); + len = strftime(buf, sizeof(buf), "%z (%Z)", tm); + ATF_REQUIRE(len > 0); + ATF_CHECK_STREQ(expect, buf); +} + ATF_TC(thin_jail); ATF_TC_HEAD(thin_jail, tc) { @@ -92,9 +105,6 @@ ATF_TC_HEAD(thin_jail, tc) ATF_TC_BODY(thin_jail, tc) { const struct tzcase *tzcase = tzcases; - char buf[128]; - struct tm *tm; - size_t len; /* prepare chroot */ ATF_REQUIRE_EQ(0, mkdir("root", 0755)); @@ -105,10 +115,7 @@ ATF_TC_BODY(thin_jail, tc) ATF_REQUIRE_EQ(0, chdir("/")); /* check timezone */ unsetenv("TZ"); - ATF_REQUIRE((tm = localtime(&then)) != NULL); - len = strftime(buf, sizeof(buf), "%z (%Z)", tm); - ATF_REQUIRE(len > 0); - ATF_CHECK_STREQ(tzcase->expect, buf); + test_tz(tzcase->expect); } #ifdef DETECT_TZ_CHANGES @@ -309,15 +316,8 @@ ATF_TC_BODY(detect_tz_changes, tc) static void test_tz_env(const char *tzval, const char *expect) { - char buf[128]; - struct tm *tm; - size_t len; - setenv("TZ", tzval, 1); - ATF_REQUIRE((tm = localtime(&then)) != NULL); - len = strftime(buf, sizeof(buf), "%z (%Z)", tm); - ATF_REQUIRE(len > 0); - ATF_CHECK_STREQ(expect, buf); + test_tz(expect); } ATF_TC(tz_env); @@ -333,6 +333,31 @@ ATF_TC_BODY(tz_env, tc) test_tz_env(tzcase->tzfn, tzcase->expect); } +ATF_TC(setugid); +ATF_TC_HEAD(setugid, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test setugid process"); + atf_tc_set_md_var(tc, "require.user", "root"); +} +ATF_TC_BODY(setugid, tc) +{ + const struct tzcase *tzcase = tzcases; + + /* prepare chroot */ + ATF_REQUIRE_EQ(0, mkdir("root", 0755)); + ATF_REQUIRE_EQ(0, mkdir("root/etc", 0755)); + change_tz(tzcase->tzfn); + /* enter chroot */ + ATF_REQUIRE_EQ(0, chroot("root")); + ATF_REQUIRE_EQ(0, chdir("/")); + /* become setugid */ + ATF_REQUIRE_EQ(0, seteuid(UID_NOBODY)); + ATF_REQUIRE(issetugid()); + /* check timezone */ + unsetenv("TZ"); + test_tz(tzcases->expect); +} + ATF_TC(tz_env_setugid); ATF_TC_HEAD(tz_env_setugid, tc) { @@ -342,7 +367,7 @@ ATF_TC_HEAD(tz_env_setugid, tc) } ATF_TC_BODY(tz_env_setugid, tc) { - const struct tzcase *tzcase; + const struct tzcase *tzcase = tzcases; ATF_REQUIRE_EQ(0, seteuid(UID_NOBODY)); ATF_REQUIRE(issetugid()); @@ -359,6 +384,7 @@ ATF_TP_ADD_TCS(tp) ATF_TP_ADD_TC(tp, detect_tz_changes); #endif /* DETECT_TZ_CHANGES */ ATF_TP_ADD_TC(tp, tz_env); + ATF_TP_ADD_TC(tp, setugid); ATF_TP_ADD_TC(tp, tz_env_setugid); return (atf_no_error()); } diff --git a/libexec/rc/rc.d/bluetooth b/libexec/rc/rc.d/bluetooth index 22bd5078034d..193fd969967f 100755 --- a/libexec/rc/rc.d/bluetooth +++ b/libexec/rc/rc.d/bluetooth @@ -127,8 +127,17 @@ bluetooth_setup_stack() > /dev/null 2>&1 || return 1 # Initilalize HCI node - ${hccontrol} -n ${dev}hci reset \ - > /dev/null 2>&1 || return 1 + for loop in 1 2 3 + do + ${hccontrol} -n ${dev}hci reset \ + > /dev/null 2>&1 && break + if [ ${loop} -eq 3 ] + then + warn Reset failed three times, giving up. + return 1 + fi + warn Reset failed, retrying. + done ${hccontrol} -n ${dev}hci read_bd_addr \ > /dev/null 2>&1 || return 1 diff --git a/libexec/rc/rc.d/moused b/libexec/rc/rc.d/moused index 6f1b95af0f0a..aaf0dd0890a8 100755 --- a/libexec/rc/rc.d/moused +++ b/libexec/rc/rc.d/moused @@ -70,6 +70,7 @@ moused_start() esac for ttyv in /dev/ttyv* ; do + [ "$ttyv" = '/dev/ttyv*' ] && break vidcontrol < ${ttyv} ${mousechar_arg} -m on done } diff --git a/libexec/rc/rc.d/syscons b/libexec/rc/rc.d/syscons index 325628a83d8c..b01b648ace6e 100755 --- a/libexec/rc/rc.d/syscons +++ b/libexec/rc/rc.d/syscons @@ -238,6 +238,7 @@ syscons_configure_keyboard() sc_init echo -n ' allscreens_kbd' for ttyv in /dev/ttyv*; do + [ "$ttyv" = '/dev/ttyv*' ] && break kbdcontrol ${allscreens_kbdflags} < ${ttyv} > ${ttyv} 2>&1 done fi @@ -382,6 +383,7 @@ syscons_start() sc_init echo -n ' allscreens' for ttyv in /dev/ttyv*; do + [ "$ttyv" = '/dev/ttyv*' ] && break vidcontrol ${allscreens_flags} < ${ttyv} > ${ttyv} 2>&1 done fi diff --git a/sbin/recoverdisk/recoverdisk.1 b/sbin/recoverdisk/recoverdisk.1 index 9f1deb4c0c23..90849755ea0c 100644 --- a/sbin/recoverdisk/recoverdisk.1 +++ b/sbin/recoverdisk/recoverdisk.1 @@ -31,6 +31,7 @@ .Sh SYNOPSIS .Nm .Op Fl b Ar bigsize +.Op Fl i Ar interval .Op Fl r Ar readlist .Op Fl s Ar interval .Op Fl u Ar pattern @@ -109,6 +110,11 @@ reports for character and block devices or if .Ar source is a regular file. +.It Fl i Ar pause +.Xr sleep 3 +this long between reads. This reduces the load on the +.Ar source +device and the system in general. .It Fl p Ar pause .Xr sleep 3 this long whenever a read fails. This makes the diff --git a/sbin/recoverdisk/recoverdisk.c b/sbin/recoverdisk/recoverdisk.c index f13a1f211863..5971f78738ac 100644 --- a/sbin/recoverdisk/recoverdisk.c +++ b/sbin/recoverdisk/recoverdisk.c @@ -28,6 +28,11 @@ #include <time.h> #include <unistd.h> +/* + * This is a compromise between speed and wasted effort + */ +#define COMPROMISE_SIZE (128<<10) + struct lump { uint64_t start; uint64_t len; @@ -51,6 +56,7 @@ static uint64_t medium_read; static uint64_t small_read; static uint64_t total_size; static uint64_t done_size; +static uint64_t wasted_size; static char *input; static char *write_worklist_file = NULL; static char *read_worklist_file = NULL; @@ -61,6 +67,7 @@ static FILE *log_file = NULL; static char *work_buf; static char *pattern_buf; static double error_pause; +static double interval; static unsigned nlumps; static double n_reads, n_good_reads; @@ -418,7 +425,8 @@ fill_buf(char *buf, int64_t len, const char *pattern) static void usage(void) { - fprintf(stderr, "usage: recoverdisk [-b big_read] [-r readlist] " + fprintf(stderr, "usage: recoverdisk " + "[-b big_read] [-i interval ] [-r readlist] " "[-s interval] [-w writelist] source [destination]\n"); /* XXX update */ exit(1); @@ -486,6 +494,7 @@ attempt_one_lump(time_t t_now) fflush(log_file); } } else { + wasted_size += sz; printf("%14ju %7ju read error %d: (%s)", (uintmax_t)lp->start, (uintmax_t)sz, error, strerror(error)); @@ -557,8 +566,6 @@ determine_read_sizes(void) u_int sectorsize; off_t stripesize; - determine_total_size(); - #ifdef DIOCGSECTORSIZE if (small_read == 0) { error = ioctl(read_fd, DIOCGSECTORSIZE, §orsize); @@ -572,8 +579,8 @@ determine_read_sizes(void) #endif if (small_read == 0) { - printf("Assuming 512 for small_read\n"); small_read = 512; + printf("# Defaulting small_read to %ju\n", (uintmax_t)small_read); } if (medium_read && (medium_read % small_read)) { @@ -593,13 +600,13 @@ determine_read_sizes(void) #ifdef DIOCGSTRIPESIZE if (medium_read == 0) { error = ioctl(read_fd, DIOCGSTRIPESIZE, &stripesize); - if (error < 0 || stripesize < 0) { + if (error < 0 || stripesize <= 0) { // nope } else if ((uint64_t)stripesize < small_read) { // nope } else if (stripesize % small_read) { // nope - } else if (0 < stripesize && stripesize < (128<<10)) { + } else if (stripesize <= COMPROMISE_SIZE) { medium_read = stripesize; printf("# Got medium_read from DIOCGSTRIPESIZE: %ju\n", (uintmax_t)medium_read @@ -607,6 +614,7 @@ determine_read_sizes(void) } } #endif + #if defined(DIOCGFWSECTORS) && defined(DIOCGFWHEADS) if (medium_read == 0) { u_int fwsectors = 0, fwheads = 0; @@ -616,10 +624,16 @@ determine_read_sizes(void) error = ioctl(read_fd, DIOCGFWHEADS, &fwheads); if (error) fwheads = 0; - if (fwsectors && fwheads) { + if (fwsectors * fwheads * small_read <= COMPROMISE_SIZE) { medium_read = fwsectors * fwheads * small_read; printf( - "# Got medium_read from DIOCGFW{SECTORS,HEADS}: %ju\n", + "# Got medium_read from DIOCGFW{SECTORS*HEADS}: %ju\n", + (uintmax_t)medium_read + ); + } else if (fwsectors * small_read <= COMPROMISE_SIZE) { + medium_read = fwsectors * small_read; + printf( + "# Got medium_read from DIOCGFWSECTORS: %ju\n", (uintmax_t)medium_read ); } @@ -627,10 +641,11 @@ determine_read_sizes(void) #endif if (big_read == 0 && medium_read != 0) { - if (medium_read > (64<<10)) { + if (medium_read * 2 > COMPROMISE_SIZE) { big_read = medium_read; + medium_read = 0; } else { - big_read = 128 << 10; + big_read = COMPROMISE_SIZE; big_read -= big_read % medium_read; } printf("# Got big_read from medium_read: %ju\n", @@ -639,12 +654,16 @@ determine_read_sizes(void) } if (big_read == 0) { - big_read = 128 << 10; + big_read = COMPROMISE_SIZE; + big_read -= big_read % small_read; printf("# Defaulting big_read to %ju\n", (uintmax_t)big_read ); } + if (medium_read >= big_read) + medium_read = 0; + if (medium_read == 0) { /* * We do not want to go directly to single sectors, but @@ -662,12 +681,20 @@ determine_read_sizes(void) (uintmax_t)medium_read ); } - fprintf(stderr, - "# Bigsize = %ju, medium_read = %ju, small_read = %ju\n", + printf("# Bigsize = %ju, medium_read = %ju, small_read = %ju\n", (uintmax_t)big_read, (uintmax_t)medium_read, (uintmax_t)small_read); -} + assert(0 < small_read); + + assert(0 < medium_read); + assert(medium_read >= small_read); + assert(medium_read <= big_read); + assert(medium_read % small_read == 0); + assert(0 < big_read); + assert(big_read >= medium_read); + assert(big_read % small_read == 0); +} /**********************************************************************/ @@ -687,15 +714,14 @@ monitor_read_sizes(uint64_t failed_size) ); big_read = medium_read; medium_read = small_read; + wasted_size = 0; return; } - if (failed_size > small_read) { - if (n_reads < n_good_reads + 100) - return; + if (big_read > small_read && wasted_size / small_read > 200) { fprintf( stderr, - "Too many failures." + "Too much wasted effort." " (%.0f bad of %.0f)" " Shifting to small_reads.\n", n_reads - n_good_reads, n_reads @@ -719,11 +745,14 @@ main(int argc, char * const argv[]) setbuf(stdout, NULL); setbuf(stderr, NULL); - while ((ch = getopt(argc, argv, "b:l:p:m:r:w:s:t:u:v")) != -1) { + while ((ch = getopt(argc, argv, "b:i:l:p:m:r:w:s:t:u:v")) != -1) { switch (ch) { case 'b': big_read = strtoul(optarg, NULL, 0); break; + case 'i': + interval = strtod(optarg, NULL); + break; case 'l': log_file = fopen(optarg, "a"); if (log_file == NULL) { @@ -774,6 +803,8 @@ main(int argc, char * const argv[]) if (read_fd < 0) err(1, "Cannot open read descriptor %s", argv[0]); + determine_total_size(); + determine_read_sizes(); work_buf = malloc(big_read); @@ -816,6 +847,9 @@ main(int argc, char * const argv[]) t_save = t_first; unsaved = 0; while (!aborting) { + if (interval > 0) { + usleep((unsigned long)(1e6 * interval)); + } t_now = time(NULL); sz = attempt_one_lump(t_now); error = errno; diff --git a/sbin/veriexec/veriexec.8 b/sbin/veriexec/veriexec.8 index 8e99f1d61faf..8352dd8e5e49 100644 --- a/sbin/veriexec/veriexec.8 +++ b/sbin/veriexec/veriexec.8 @@ -195,7 +195,7 @@ and be strict about enforcing certificate validity: .Ed .Nm -will look for a detatched signature that it recognizes, such as +will look for a detached signature that it recognizes, such as .Pa manifest.asc (OpenPGP) or .Pa manifest.*sig diff --git a/secure/lib/libcrypto/modules/legacy/Makefile b/secure/lib/libcrypto/modules/legacy/Makefile index c16919ddcd94..db05f212f62a 100644 --- a/secure/lib/libcrypto/modules/legacy/Makefile +++ b/secure/lib/libcrypto/modules/legacy/Makefile @@ -1,7 +1,7 @@ SHLIB_NAME?= legacy.so LIBADD= crypto -SRCS+= legacyprov.c prov_running.c +SRCS+= legacyprov.c prov_running.c params_idx.c # ciphers SRCS+= ciphercommon.c ciphercommon_hw.c ciphercommon_block.c \ @@ -21,11 +21,12 @@ SRCS+= digestcommon.c SRCS+= md4_prov.c wp_prov.c ripemd_prov.c # kdfs -SRCS+= pbkdf1.c +SRCS+= pbkdf1.c pvkkdf.c .include <bsd.lib.mk> -.PATH: ${LCRYPTO_SRC}/providers/implementations/ciphers \ +.PATH: ${LCRYPTO_SRC}/crypto \ + ${LCRYPTO_SRC}/providers/implementations/ciphers \ ${LCRYPTO_SRC}/providers/implementations/digests \ ${LCRYPTO_SRC}/providers/implementations/kdfs \ ${LCRYPTO_SRC}/ssl diff --git a/share/man/man4/epair.4 b/share/man/man4/epair.4 index 342b15b5612a..0014836b01ea 100644 --- a/share/man/man4/epair.4 +++ b/share/man/man4/epair.4 @@ -25,7 +25,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd August 12, 2025 +.Dd September 2, 2025 .Dt EPAIR 4 .Os .Sh NAME @@ -108,6 +108,28 @@ As with any other Ethernet interface, can have a .Xr vlan 4 configured on top of it. +.Pp +The +.Nm +has RXCSUM and RXCSUM6 enabled because it may receive a packet where the +checksum has already been validated by a physical interface. +The +.Nm +supports TXCSUM and TXCSUM6 for TCP and UDP, but only by forwarding the order +to compute the checksum. +Thus, when using an +.Nm +interface, a TCP or UDP sender can offload checksum computation +to a physical interface. +Note that, in case the packet does not leave the host, the checksum is +unnecessary and will be ignored if offloaded. +TXCSUM and TXCSUM6 are synchronized between the +.Nm +interface pair (i.e., enabling/disabling the capability on one end +enables/disables it on the other end). +In case one end is in a bridge and the bridge disabled TXCSUM or TXCSUM6, +this avoids a sender to send packets with checksum offloading into the +bridge by using the other end. .Sh SEE ALSO .Xr ioctl 2 , .Xr altq 4 , diff --git a/share/man/man4/syncache.4 b/share/man/man4/syncache.4 index e92502fd15ff..f83e9b083e45 100644 --- a/share/man/man4/syncache.4 +++ b/share/man/man4/syncache.4 @@ -10,7 +10,7 @@ .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. .\" -.Dd April 12, 2021 +.Dd August 30, 2025 .Dt SYNCACHE 4 .Os .Sh NAME @@ -39,6 +39,8 @@ MIBs for controlling TCP SYN caching .Nm sysctl Cm net.inet.tcp.syncache.count .It .Nm sysctl Cm net.inet.tcp.syncache.see_other +.It +.Nm sysctl Cm net.inet.tcp.syncache.rst_on_sock_fail .El .Sh DESCRIPTION The @@ -107,6 +109,18 @@ and run only with set .Va net.inet.tcp.syncookies_only to 1. +To use +.Nm syncookies +to handle bucket overflows in the +.Nm syncache +set +.Va net.inet.tcp.syncookies +to 1. +The default value for +.Va net.inet.tcp.syncookies_only +is 0 and the default value for +.Va net.inet.tcp.syncookies +is 1. .Pp The .Nm @@ -169,6 +183,9 @@ However, extra .Xr ucred 9 referencing is required on every incoming SYN packet processed. The default is off. +.It Va rst_on_sock_fail +Send a TCP RST segment if the socket allocation fails. +The default is on. .El .Pp Statistics on the performance of the @@ -206,8 +223,16 @@ Entries dropped due to ICMP unreachable messages. Failures to allocate new .Nm entry. +.It Li "cookies sent" +SYN cookies sent in SYN ACK segments. .It Li "cookies received" -Connections created from segment containing ACK. +ACK segments with valid syncookies which resulted in TCP connection +establishment. +.It Li "spurious cookies rejected" +Received ACKs, for which the syncache lookup failed and also no syncookie was +recently sent. +.It Li "failed cookies rejected" +Received ACKs for which the syncookie validation failed. .El .Sh SEE ALSO .Xr netstat 1 , diff --git a/sys/compat/linuxkpi/common/include/linux/ieee80211.h b/sys/compat/linuxkpi/common/include/linux/ieee80211.h index 33850359869f..17041bb03ce8 100644 --- a/sys/compat/linuxkpi/common/include/linux/ieee80211.h +++ b/sys/compat/linuxkpi/common/include/linux/ieee80211.h @@ -408,6 +408,14 @@ enum ieee80211_sta_state { IEEE80211_STA_AUTHORIZED = 4, /* 802.1x */ }; +enum ieee80211_sta_rx_bandwidth { + IEEE80211_STA_RX_BW_20 = 0, + IEEE80211_STA_RX_BW_40, + IEEE80211_STA_RX_BW_80, + IEEE80211_STA_RX_BW_160, + IEEE80211_STA_RX_BW_320, +}; + enum ieee80211_tx_info_flags { /* XXX TODO .. right shift numbers - not sure where that came from? */ IEEE80211_TX_CTL_AMPDU = BIT(0), diff --git a/sys/compat/linuxkpi/common/include/net/mac80211.h b/sys/compat/linuxkpi/common/include/net/mac80211.h index 0106e6648bd4..8de03410c6b6 100644 --- a/sys/compat/linuxkpi/common/include/net/mac80211.h +++ b/sys/compat/linuxkpi/common/include/net/mac80211.h @@ -737,7 +737,7 @@ struct ieee80211_link_sta { struct ieee80211_he_6ghz_capa he_6ghz_capa; struct ieee80211_sta_eht_cap eht_cap; uint8_t rx_nss; - enum ieee80211_sta_rx_bw bandwidth; + enum ieee80211_sta_rx_bandwidth bandwidth; enum ieee80211_smps_mode smps_mode; struct ieee80211_sta_agg agg; struct ieee80211_sta_txpwr txpwr; diff --git a/sys/compat/linuxkpi/common/src/linux_80211.c b/sys/compat/linuxkpi/common/src/linux_80211.c index 3f850653bc7c..f0881773726f 100644 --- a/sys/compat/linuxkpi/common/src/linux_80211.c +++ b/sys/compat/linuxkpi/common/src/linux_80211.c @@ -401,7 +401,7 @@ lkpi_80211_dump_stas(SYSCTL_HANDLER_ARGS) return (0); } -static enum ieee80211_sta_rx_bw +static enum ieee80211_sta_rx_bandwidth lkpi_cw_to_rx_bw(enum nl80211_chan_width cw) { switch (cw) { @@ -425,7 +425,7 @@ lkpi_cw_to_rx_bw(enum nl80211_chan_width cw) } static enum nl80211_chan_width -lkpi_rx_bw_to_cw(enum ieee80211_sta_rx_bw rx_bw) +lkpi_rx_bw_to_cw(enum ieee80211_sta_rx_bandwidth rx_bw) { switch (rx_bw) { case IEEE80211_STA_RX_BW_20: @@ -446,7 +446,7 @@ lkpi_sync_chanctx_cw_from_rx_bw(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta) { struct ieee80211_chanctx_conf *chanctx_conf; - enum ieee80211_sta_rx_bw old_bw; + enum ieee80211_sta_rx_bandwidth old_bw; uint32_t changed; chanctx_conf = rcu_dereference_protected(vif->bss_conf.chanctx_conf, @@ -551,7 +551,7 @@ static void lkpi_sta_sync_vht_from_ni(struct ieee80211_vif *vif, struct ieee80211_sta *sta, struct ieee80211_node *ni) { - enum ieee80211_sta_rx_bw bw; + enum ieee80211_sta_rx_bandwidth bw; uint32_t width; int rx_nss; uint16_t rx_mcs_map; @@ -1890,7 +1890,25 @@ lkpi_update_dtim_tsf(struct ieee80211_vif *vif, struct ieee80211_node *ni, vif->bss_conf.beacon_int = 16; bss_changed |= BSS_CHANGED_BEACON_INT; } - if (vif->bss_conf.dtim_period != ni->ni_dtim_period && + + /* + * lkpi_iv_sta_recv_mgmt() will directly call into this function. + * iwlwifi(4) in iwl_mvm_bss_info_changed_station_common() will + * stop seesion protection the moment it sees + * BSS_CHANGED_BEACON_INFO (with the expectations that it was + * "a beacon from the associated AP"). It will also update + * the beacon filter in that case. This is the only place + * we set the BSS_CHANGED_BEACON_INFO on the non-teardown + * path so make sure we only do run this check once we are + * assoc. (*iv_recv_mgmt)() will be called before we enter + * here so the ni will be updates with information from the + * beacon via net80211::sta_recv_mgmt(). We also need to + * make sure we do not do it on every beacon we still may + * get so only do if something changed. vif->bss_conf.dtim_period + * should be 0 as we start up (we also reset it on teardown). + */ + if (vif->cfg.assoc && + vif->bss_conf.dtim_period != ni->ni_dtim_period && ni->ni_dtim_period > 0) { vif->bss_conf.dtim_period = ni->ni_dtim_period; bss_changed |= BSS_CHANGED_BEACON_INFO; @@ -3810,6 +3828,7 @@ lkpi_iv_sta_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0, enum ieee80211_bss_changed bss_changed; lvif = VAP_TO_LVIF(ni->ni_vap); + vif = LVIF_TO_VIF(lvif); lvif->iv_recv_mgmt(ni, m0, subtype, rxs, rssi, nf); @@ -3817,13 +3836,18 @@ lkpi_iv_sta_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0, case IEEE80211_FC0_SUBTYPE_PROBE_RESP: break; case IEEE80211_FC0_SUBTYPE_BEACON: - lvif->beacons++; + /* + * Only count beacons when assoc. SCAN has its own logging. + * This is for connection/beacon loss/session protection almost + * over debugging when trying to get into a stable RUN state. + */ + if (vif->cfg.assoc) + lvif->beacons++; break; default: return; } - vif = LVIF_TO_VIF(lvif); lhw = ni->ni_ic->ic_softc; hw = LHW_TO_HW(lhw); @@ -4059,13 +4083,9 @@ lkpi_ic_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], * Modern chipset/fw/drv will do A-MPDU in drv/fw and fail * to do so if they cannot do the crypto too. */ - if (!lkpi_hwcrypto && ieee80211_hw_check(hw, AMPDU_AGGREGATION)) + if (!lkpi_hwcrypto && IEEE80211_CONF_AMPDU_OFFLOAD(ic)) vap->iv_flags_ht &= ~IEEE80211_FHT_AMPDU_RX; #endif -#if defined(LKPI_80211_HT) - /* 20250125-BZ Keep A-MPDU TX cleared until we sorted out AddBA for all drivers. */ - vap->iv_flags_ht &= ~IEEE80211_FHT_AMPDU_TX; -#endif if (hw->max_listen_interval == 0) hw->max_listen_interval = 7 * (ic->ic_lintval / ic->ic_bintval); @@ -6609,6 +6629,14 @@ linuxkpi_ieee80211_ifattach(struct ieee80211_hw *hw) if (ieee80211_hw_check(hw, SUPPORTS_TX_FRAG)) ic->ic_flags_ext |= IEEE80211_FEXT_FRAG_OFFLOAD; + /* Does HW support full AMPDU[-TX] offload? */ + if (ieee80211_hw_check(hw, AMPDU_AGGREGATION)) + ic->ic_flags_ext |= IEEE80211_FEXT_AMPDU_OFFLOAD; +#ifdef __notyet__ + if (ieee80211_hw_check(hw, TX_AMSDU)) + if (ieee80211_hw_check(hw, SUPPORTS_AMSDU_IN_AMPDU)) +#endif + /* * The wiphy variables report bitmasks of avail antennas. * (*get_antenna) get the current bitmask sets which can be diff --git a/sys/dev/ath/ath_rate/sample/sample.c b/sys/dev/ath/ath_rate/sample/sample.c index 291d1ec64ed7..79bf08678249 100644 --- a/sys/dev/ath/ath_rate/sample/sample.c +++ b/sys/dev/ath/ath_rate/sample/sample.c @@ -179,7 +179,7 @@ ath_rate_sample_find_min_pktlength(struct ath_softc *sc, const struct txschedule *sched = &sn->sched[rix0]; int max_pkt_length = 65530; // ATH_AGGR_MAXSIZE // Note: this may not be true in all cases; need to check? - int is_ht40 = (an->an_node.ni_chw == IEEE80211_STA_RX_BW_40); + int is_ht40 = (an->an_node.ni_chw == NET80211_STA_RX_BW_40); // Note: not great, but good enough.. int idx = is_ht40 ? MCS_HT40 : MCS_HT20; @@ -979,7 +979,7 @@ update_stats(struct ath_softc *sc, struct ath_node *an, const int size_bin = size_to_bin(frame_size); const int size = bin_to_size(size_bin); int tt; - int is_ht40 = (an->an_node.ni_chw == IEEE80211_STA_RX_BW_40); + int is_ht40 = (an->an_node.ni_chw == NET80211_STA_RX_BW_40); int pct; if (!IS_RATE_DEFINED(sn, rix0)) @@ -1365,7 +1365,7 @@ ath_rate_ctl_reset(struct ath_softc *sc, struct ieee80211_node *ni) continue; printf(" %d %s/%d", dot11rate(rt, rix), dot11rate_label(rt, rix), calc_usecs_unicast_packet(sc, 1600, rix, 0,0, - (ni->ni_chw == IEEE80211_STA_RX_BW_40))); + (ni->ni_chw == NET80211_STA_RX_BW_40))); } printf("\n"); } @@ -1396,7 +1396,7 @@ ath_rate_ctl_reset(struct ath_softc *sc, struct ieee80211_node *ni) sn->stats[y][rix].perfect_tx_time = calc_usecs_unicast_packet(sc, size, rix, 0, 0, - (ni->ni_chw == IEEE80211_STA_RX_BW_40)); + (ni->ni_chw == NET80211_STA_RX_BW_40)); sn->stats[y][rix].average_tx_time = sn->stats[y][rix].perfect_tx_time; } diff --git a/sys/dev/ath/if_ath_tx_ht.c b/sys/dev/ath/if_ath_tx_ht.c index e7ee029fecf0..f42058bacb0d 100644 --- a/sys/dev/ath/if_ath_tx_ht.c +++ b/sys/dev/ath/if_ath_tx_ht.c @@ -283,7 +283,7 @@ ath_tx_rate_fill_rcflags(struct ath_softc *sc, struct ath_buf *bf) if (IS_HT_RATE(rate)) { rc[i].flags |= ATH_RC_HT_FLAG; - if (ni->ni_chw == IEEE80211_STA_RX_BW_40) + if (ni->ni_chw == NET80211_STA_RX_BW_40) rc[i].flags |= ATH_RC_CW40_FLAG; /* @@ -295,13 +295,13 @@ ath_tx_rate_fill_rcflags(struct ath_softc *sc, struct ath_buf *bf) * and doesn't return the fractional part, so * we are always "out" by some amount. */ - if (ni->ni_chw == IEEE80211_STA_RX_BW_40 && + if (ni->ni_chw == NET80211_STA_RX_BW_40 && ieee80211_ht_check_tx_shortgi_40(ni) && (bf->bf_flags & ATH_BUF_TOA_PROBE) == 0) { rc[i].flags |= ATH_RC_SGI_FLAG; } - if (ni->ni_chw == IEEE80211_STA_RX_BW_20 && + if (ni->ni_chw == NET80211_STA_RX_BW_20 && ieee80211_ht_check_tx_shortgi_20(ni) && (bf->bf_flags & ATH_BUF_TOA_PROBE) == 0) { rc[i].flags |= ATH_RC_SGI_FLAG; diff --git a/sys/dev/cxgbe/t4_main.c b/sys/dev/cxgbe/t4_main.c index 9e91250cb61c..9756a6945384 100644 --- a/sys/dev/cxgbe/t4_main.c +++ b/sys/dev/cxgbe/t4_main.c @@ -9016,7 +9016,7 @@ sysctl_loadavg(SYSCTL_HANDLER_ARGS) rc = begin_synchronized_op(sc, NULL, SLEEP_OK | INTR_OK, "t4lavg"); if (rc) return (rc); - if (hw_all_ok(sc)) + if (!hw_all_ok(sc)) rc = ENXIO; else { param = V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_DEV) | diff --git a/sys/dev/mpr/mpr.c b/sys/dev/mpr/mpr.c index d1c572e40669..262d6b58b705 100644 --- a/sys/dev/mpr/mpr.c +++ b/sys/dev/mpr/mpr.c @@ -1729,6 +1729,7 @@ mpr_get_tunables(struct mpr_softc *sc) sc->enable_ssu = MPR_SSU_ENABLE_SSD_DISABLE_HDD; sc->spinup_wait_time = DEFAULT_SPINUP_WAIT; sc->use_phynum = 1; + sc->encl_min_slots = 0; sc->max_reqframes = MPR_REQ_FRAMES; sc->max_prireqframes = MPR_PRI_REQ_FRAMES; sc->max_replyframes = MPR_REPLY_FRAMES; @@ -1748,6 +1749,7 @@ mpr_get_tunables(struct mpr_softc *sc) TUNABLE_INT_FETCH("hw.mpr.enable_ssu", &sc->enable_ssu); TUNABLE_INT_FETCH("hw.mpr.spinup_wait_time", &sc->spinup_wait_time); TUNABLE_INT_FETCH("hw.mpr.use_phy_num", &sc->use_phynum); + TUNABLE_INT_FETCH("hw.mpr.encl_min_slots", &sc->encl_min_slots); TUNABLE_INT_FETCH("hw.mpr.max_reqframes", &sc->max_reqframes); TUNABLE_INT_FETCH("hw.mpr.max_prireqframes", &sc->max_prireqframes); TUNABLE_INT_FETCH("hw.mpr.max_replyframes", &sc->max_replyframes); @@ -1797,6 +1799,10 @@ mpr_get_tunables(struct mpr_softc *sc) device_get_unit(sc->mpr_dev)); TUNABLE_INT_FETCH(tmpstr, &sc->use_phynum); + snprintf(tmpstr, sizeof(tmpstr), "dev.mpr.%d.encl_min_slots", + device_get_unit(sc->mpr_dev)); + TUNABLE_INT_FETCH(tmpstr, &sc->encl_min_slots); + snprintf(tmpstr, sizeof(tmpstr), "dev.mpr.%d.max_reqframes", device_get_unit(sc->mpr_dev)); TUNABLE_INT_FETCH(tmpstr, &sc->max_reqframes); @@ -1951,6 +1957,10 @@ mpr_setup_sysctl(struct mpr_softc *sc) SYSCTL_ADD_UQUAD(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), OID_AUTO, "prp_page_alloc_fail", CTLFLAG_RD, &sc->prp_page_alloc_fail, "PRP page allocation failures"); + + SYSCTL_ADD_INT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), + OID_AUTO, "encl_min_slots", CTLFLAG_RW, &sc->encl_min_slots, 0, + "force enclosure minimum slots"); } static struct mpr_debug_string { diff --git a/sys/dev/mpr/mpr_mapping.c b/sys/dev/mpr/mpr_mapping.c index f9a9ac1c53d0..38aa4dfc7ef2 100644 --- a/sys/dev/mpr/mpr_mapping.c +++ b/sys/dev/mpr/mpr_mapping.c @@ -2785,6 +2785,8 @@ mpr_mapping_enclosure_dev_status_change_event(struct mpr_softc *sc, * DPM, if it's being used. */ if (enc_idx != MPR_ENCTABLE_BAD_IDX) { + u16 new_num_slots; + et_entry = &sc->enclosure_table[enc_idx]; if (et_entry->init_complete && !et_entry->missing_count) { @@ -2796,6 +2798,17 @@ mpr_mapping_enclosure_dev_status_change_event(struct mpr_softc *sc, et_entry->enc_handle = le16toh(event_data-> EnclosureHandle); et_entry->start_slot = le16toh(event_data->StartSlot); + new_num_slots = le16toh(event_data->NumSlots); + if (new_num_slots < sc->encl_min_slots) { + mpr_dprint(sc, MPR_MAPPING, "%s: Enclosure %d num_slots %d, overriding with %d.\n", + __func__, enc_idx, new_num_slots, sc->encl_min_slots); + new_num_slots = sc->encl_min_slots; + } + if (et_entry->num_slots != new_num_slots) { + mpr_dprint(sc, MPR_MAPPING, "%s: Enclosure %d old num_slots %d, new %d.\n", + __func__, enc_idx, et_entry->num_slots, sc->encl_min_slots); + et_entry->num_slots = new_num_slots; + } saved_phy_bits = et_entry->phy_bits; et_entry->phy_bits |= le32toh(event_data->PhyBits); if (saved_phy_bits != et_entry->phy_bits) @@ -2858,6 +2871,11 @@ mpr_mapping_enclosure_dev_status_change_event(struct mpr_softc *sc, et_entry->start_index = MPR_MAPTABLE_BAD_IDX; et_entry->dpm_entry_num = MPR_DPM_BAD_IDX; et_entry->num_slots = le16toh(event_data->NumSlots); + if (et_entry->num_slots < sc->encl_min_slots) { + mpr_dprint(sc, MPR_ERROR | MPR_MAPPING, "%s: Enclosure %d num_slots is %d, overriding with %d.\n", + __func__, enc_idx, et_entry->num_slots, sc->encl_min_slots); + et_entry->num_slots = sc->encl_min_slots; + } et_entry->start_slot = le16toh(event_data->StartSlot); et_entry->phy_bits = le32toh(event_data->PhyBits); } diff --git a/sys/dev/mpr/mprvar.h b/sys/dev/mpr/mprvar.h index 0f1743f4266e..93f3fbffe079 100644 --- a/sys/dev/mpr/mprvar.h +++ b/sys/dev/mpr/mprvar.h @@ -366,6 +366,7 @@ struct mpr_softc { int spinup_wait_time; int use_phynum; int dump_reqs_alltypes; + int encl_min_slots; uint64_t chain_alloc_fail; uint64_t prp_page_alloc_fail; struct sysctl_ctx_list sysctl_ctx; diff --git a/sys/dev/mwl/if_mwl.c b/sys/dev/mwl/if_mwl.c index 0e2eb0b2d8fe..c885968dfe15 100644 --- a/sys/dev/mwl/if_mwl.c +++ b/sys/dev/mwl/if_mwl.c @@ -4017,7 +4017,7 @@ mkpeerinfo(MWL_HAL_PEERINFO *pi, const struct ieee80211_node *ni) pi->HTCapabilitiesInfo &= ~IEEE80211_HTCAP_SHORTGI40; if ((vap->iv_flags_ht & IEEE80211_FHT_SHORTGI20) == 0) pi->HTCapabilitiesInfo &= ~IEEE80211_HTCAP_SHORTGI20; - if (ni->ni_chw != IEEE80211_STA_RX_BW_40) + if (ni->ni_chw != NET80211_STA_RX_BW_40) pi->HTCapabilitiesInfo &= ~IEEE80211_HTCAP_CHWIDTH40; } return pi; diff --git a/sys/dev/rtwn/rtl8812a/r12a_tx.c b/sys/dev/rtwn/rtl8812a/r12a_tx.c index acb238316559..0ca1ebd37757 100644 --- a/sys/dev/rtwn/rtl8812a/r12a_tx.c +++ b/sys/dev/rtwn/rtl8812a/r12a_tx.c @@ -101,12 +101,12 @@ r12a_tx_set_vht_bw(struct rtwn_softc *sc, void *buf, struct ieee80211_node *ni) prim_chan = r12a_get_primary_channel(sc, ni->ni_chan); - if (ieee80211_vht_check_tx_bw(ni, IEEE80211_STA_RX_BW_80)) { + if (ieee80211_vht_check_tx_bw(ni, NET80211_STA_RX_BW_80)) { txd->txdw5 |= htole32(SM(R12A_TXDW5_DATA_BW, R12A_TXDW5_DATA_BW80)); txd->txdw5 |= htole32(SM(R12A_TXDW5_DATA_PRIM_CHAN, prim_chan)); - } else if (ieee80211_vht_check_tx_bw(ni, IEEE80211_STA_RX_BW_40)) { + } else if (ieee80211_vht_check_tx_bw(ni, NET80211_STA_RX_BW_40)) { txd->txdw5 |= htole32(SM(R12A_TXDW5_DATA_BW, R12A_TXDW5_DATA_BW40)); txd->txdw5 |= htole32(SM(R12A_TXDW5_DATA_PRIM_CHAN, diff --git a/sys/dev/ufshci/ufshci.h b/sys/dev/ufshci/ufshci.h index b96d82ff836e..b055d2d2d769 100644 --- a/sys/dev/ufshci/ufshci.h +++ b/sys/dev/ufshci/ufshci.h @@ -716,6 +716,42 @@ struct ufshci_device_descriptor { _Static_assert(sizeof(struct ufshci_device_descriptor) == 89, "bad size for ufshci_device_descriptor"); +/* Defines the bit field of dExtendedUfsFeaturesSupport. */ +enum ufshci_desc_wb_ext_ufs_feature { + UFSHCI_DESC_EXT_UFS_FEATURE_FFU = (1 << 0), + UFSHCI_DESC_EXT_UFS_FEATURE_PSA = (1 << 1), + UFSHCI_DESC_EXT_UFS_FEATURE_DEV_LIFE_SPAN = (1 << 2), + UFSHCI_DESC_EXT_UFS_FEATURE_REFRESH_OP = (1 << 3), + UFSHCI_DESC_EXT_UFS_FEATURE_TOO_HIGH_TEMP = (1 << 4), + UFSHCI_DESC_EXT_UFS_FEATURE_TOO_LOW_TEMP = (1 << 5), + UFSHCI_DESC_EXT_UFS_FEATURE_EXT_TEMP = (1 << 6), + UFSHCI_DESC_EXT_UFS_FEATURE_HPB_SUPPORT = (1 << 7), + UFSHCI_DESC_EXT_UFS_FEATURE_WRITE_BOOSTER = (1 << 8), + UFSHCI_DESC_EXT_UFS_FEATURE_PERF_THROTTLING = (1 << 9), + UFSHCI_DESC_EXT_UFS_FEATURE_ADVANCED_RPMB = (1 << 10), + UFSHCI_DESC_EXT_UFS_FEATURE_ZONED_UFS_EXTENSION = (1 << 11), + UFSHCI_DESC_EXT_UFS_FEATURE_DEV_LEVEL_EXCEPTION = (1 << 12), + UFSHCI_DESC_EXT_UFS_FEATURE_HID = (1 << 13), + UFSHCI_DESC_EXT_UFS_FEATURE_BARRIER = (1 << 14), + UFSHCI_DESC_EXT_UFS_FEATURE_CLEAR_ERROR_HISTORY = (1 << 15), + UFSHCI_DESC_EXT_UFS_FEATURE_EXT_IID = (1 << 16), + UFSHCI_DESC_EXT_UFS_FEATURE_FBO = (1 << 17), + UFSHCI_DESC_EXT_UFS_FEATURE_FAST_RECOVERY_MODE = (1 << 18), + UFSHCI_DESC_EXT_UFS_FEATURE_RPMB_VENDOR_CMD = (1 << 19), +}; + +/* Defines the bit field of bWriteBoosterBufferType. */ +enum ufshci_desc_wb_buffer_type { + UFSHCI_DESC_WB_BUF_TYPE_LU_DEDICATED = 0x00, + UFSHCI_DESC_WB_BUF_TYPE_SINGLE_SHARED = 0x01, +}; + +/* Defines the bit field of bWriteBoosterBufferPreserveUserSpaceEn. */ +enum ufshci_desc_user_space_config { + UFSHCI_DESC_WB_BUF_USER_SPACE_REDUCTION = 0x00, + UFSHCI_DESC_WB_BUF_PRESERVE_USER_SPACE = 0x01, +}; + /* * UFS Spec 4.1, section 14.1.5.3 "Configuration Descriptor" * ConfigurationDescriptor use big-endian byte ordering. @@ -1014,4 +1050,37 @@ enum ufshci_attributes { UFSHCI_ATTR_B_REFRESH_METHOD = 0x2f, }; +/* bAvailableWriteBoosterBufferSize codes (UFS WriteBooster abailable buffer + * left %) */ +enum ufshci_wb_available_buffer_Size { + UFSHCI_ATTR_WB_AVAILABLE_0 = 0x00, /* 0% buffer remains */ + UFSHCI_ATTR_WB_AVAILABLE_10 = 0x01, /* 10% buffer remains */ + UFSHCI_ATTR_WB_AVAILABLE_20 = 0x02, /* 20% buffer remains */ + UFSHCI_ATTR_WB_AVAILABLE_30 = 0x03, /* 30% buffer remains */ + UFSHCI_ATTR_WB_AVAILABLE_40 = 0x04, /* 40% buffer remains */ + UFSHCI_ATTR_WB_AVAILABLE_50 = 0x05, /* 50% buffer remains */ + UFSHCI_ATTR_WB_AVAILABLE_60 = 0x06, /* 60% buffer remains */ + UFSHCI_ATTR_WB_AVAILABLE_70 = 0x07, /* 70% buffer remains */ + UFSHCI_ATTR_WB_AVAILABLE_80 = 0x08, /* 80% buffer remains */ + UFSHCI_ATTR_WB_AVAILABLE_90 = 0x09, /* 90% buffer remains */ + UFSHCI_ATTR_WB_AVAILABLE_100 = 0x0A, /* 100% buffer remains */ +}; + +/* bWriteBoosterBufferLifeTimeEst codes (UFS WriteBooster buffer life %) */ +enum ufshci_wb_lifetime { + UFSHCI_ATTR_WB_LIFE_DISABLED = 0x00, /* Info not available */ + UFSHCI_ATTR_WB_LIFE_0_10 = 0x01, /* 0%–10% used */ + UFSHCI_ATTR_WB_LIFE_10_20 = 0x02, /* 10%–20% used */ + UFSHCI_ATTR_WB_LIFE_20_30 = 0x03, /* 20%–30% used */ + UFSHCI_ATTR_WB_LIFE_30_40 = 0x04, /* 30%–40% used */ + UFSHCI_ATTR_WB_LIFE_40_50 = 0x05, /* 40%–50% used */ + UFSHCI_ATTR_WB_LIFE_50_60 = 0x06, /* 50%–60% used */ + UFSHCI_ATTR_WB_LIFE_60_70 = 0x07, /* 60%–70% used */ + UFSHCI_ATTR_WB_LIFE_70_80 = 0x08, /* 70%–80% used */ + UFSHCI_ATTR_WB_LIFE_80_90 = 0x09, /* 80%–90% used */ + UFSHCI_ATTR_WB_LIFE_90_100 = 0x0A, /* 90%–100% used */ + UFSHCI_ATTR_WB_LIFE_EXCEEDED = + 0x0B, /* Exceeded estimated life (treat as WB disabled) */ +}; + #endif /* __UFSHCI_H__ */ diff --git a/sys/dev/ufshci/ufshci_ctrlr.c b/sys/dev/ufshci/ufshci_ctrlr.c index 37bd32665b2b..36be94b8b8b7 100644 --- a/sys/dev/ufshci/ufshci_ctrlr.c +++ b/sys/dev/ufshci/ufshci_ctrlr.c @@ -61,7 +61,7 @@ ufshci_ctrlr_enable_host_ctrlr(struct ufshci_controller *ctrlr) int ufshci_ctrlr_construct(struct ufshci_controller *ctrlr, device_t dev) { - uint32_t ver, cap, hcs, ie; + uint32_t ver, cap, hcs, ie, ahit; uint32_t timeout_period, retry_count; int error; @@ -127,6 +127,13 @@ ufshci_ctrlr_construct(struct ufshci_controller *ctrlr, device_t dev) if (error) return (error); + /* Read the UECPA register to clear */ + ufshci_mmio_read_4(ctrlr, uecpa); + + /* Diable Auto-hibernate */ + ahit = 0; + ufshci_mmio_write_4(ctrlr, ahit, ahit); + /* * The device_present(UFSHCI_HCS_REG_DP) bit becomes true if the host * controller has successfully received a Link Startup UIC command @@ -139,6 +146,16 @@ ufshci_ctrlr_construct(struct ufshci_controller *ctrlr, device_t dev) return (ENXIO); } + /* Allocate and initialize UTP Task Management Request List. */ + error = ufshci_utmr_req_queue_construct(ctrlr); + if (error) + return (error); + + /* Allocate and initialize UTP Transfer Request List or SQ/CQ. */ + error = ufshci_utr_req_queue_construct(ctrlr); + if (error) + return (error); + /* Enable additional interrupts by programming the IE register. */ ie = ufshci_mmio_read_4(ctrlr, ie); ie |= UFSHCIM(UFSHCI_IE_REG_UTRCE); /* UTR Completion */ @@ -153,19 +170,12 @@ ufshci_ctrlr_construct(struct ufshci_controller *ctrlr, device_t dev) /* TODO: Initialize interrupt Aggregation Control Register (UTRIACR) */ - /* Allocate and initialize UTP Task Management Request List. */ - error = ufshci_utmr_req_queue_construct(ctrlr); - if (error) - return (error); - - /* Allocate and initialize UTP Transfer Request List or SQ/CQ. */ - error = ufshci_utr_req_queue_construct(ctrlr); - if (error) - return (error); - /* TODO: Separate IO and Admin slot */ - /* max_hw_pend_io is the number of slots in the transfer_req_queue */ - ctrlr->max_hw_pend_io = ctrlr->transfer_req_queue.num_entries; + /* + * max_hw_pend_io is the number of slots in the transfer_req_queue. + * Reduce num_entries by one to reserve an admin slot. + */ + ctrlr->max_hw_pend_io = ctrlr->transfer_req_queue.num_entries - 1; return (0); } @@ -342,18 +352,19 @@ ufshci_ctrlr_start(struct ufshci_controller *ctrlr) return; } - /* Read Controller Descriptor (Device, Geometry)*/ + /* Read Controller Descriptor (Device, Geometry) */ if (ufshci_dev_get_descriptor(ctrlr) != 0) { ufshci_ctrlr_fail(ctrlr, false); return; } - /* TODO: Configure Write Protect */ + if (ufshci_dev_config_write_booster(ctrlr)) { + ufshci_ctrlr_fail(ctrlr, false); + return; + } /* TODO: Configure Background Operations */ - /* TODO: Configure Write Booster */ - if (ufshci_sim_attach(ctrlr) != 0) { ufshci_ctrlr_fail(ctrlr, false); return; diff --git a/sys/dev/ufshci/ufshci_dev.c b/sys/dev/ufshci/ufshci_dev.c index a0e32914e2aa..dd196b1d638b 100644 --- a/sys/dev/ufshci/ufshci_dev.c +++ b/sys/dev/ufshci/ufshci_dev.c @@ -60,6 +60,14 @@ ufshci_dev_read_geometry_descriptor(struct ufshci_controller *ctrlr, } static int +ufshci_dev_read_unit_descriptor(struct ufshci_controller *ctrlr, uint8_t lun, + struct ufshci_unit_descriptor *desc) +{ + return (ufshci_dev_read_descriptor(ctrlr, UFSHCI_DESC_TYPE_UNIT, lun, 0, + desc, sizeof(struct ufshci_unit_descriptor))); +} + +static int ufshci_dev_read_flag(struct ufshci_controller *ctrlr, enum ufshci_flags flag_type, uint8_t *flag) { @@ -114,6 +122,61 @@ ufshci_dev_set_flag(struct ufshci_controller *ctrlr, } static int +ufshci_dev_clear_flag(struct ufshci_controller *ctrlr, + enum ufshci_flags flag_type) +{ + struct ufshci_completion_poll_status status; + struct ufshci_query_param param; + + param.function = UFSHCI_QUERY_FUNC_STANDARD_WRITE_REQUEST; + param.opcode = UFSHCI_QUERY_OPCODE_CLEAR_FLAG; + param.type = flag_type; + param.index = 0; + param.selector = 0; + param.value = 0; + + status.done = 0; + ufshci_ctrlr_cmd_send_query_request(ctrlr, ufshci_completion_poll_cb, + &status, param); + ufshci_completion_poll(&status); + if (status.error) { + ufshci_printf(ctrlr, "ufshci_dev_clear_flag failed!\n"); + return (ENXIO); + } + + return (0); +} + +static int +ufshci_dev_read_attribute(struct ufshci_controller *ctrlr, + enum ufshci_attributes attr_type, uint8_t index, uint8_t selector, + uint64_t *value) +{ + struct ufshci_completion_poll_status status; + struct ufshci_query_param param; + + param.function = UFSHCI_QUERY_FUNC_STANDARD_READ_REQUEST; + param.opcode = UFSHCI_QUERY_OPCODE_READ_ATTRIBUTE; + param.type = attr_type; + param.index = index; + param.selector = selector; + param.value = 0; + + status.done = 0; + ufshci_ctrlr_cmd_send_query_request(ctrlr, ufshci_completion_poll_cb, + &status, param); + ufshci_completion_poll(&status); + if (status.error) { + ufshci_printf(ctrlr, "ufshci_dev_read_attribute failed!\n"); + return (ENXIO); + } + + *value = status.cpl.response_upiu.query_response_upiu.value_64; + + return (0); +} + +static int ufshci_dev_write_attribute(struct ufshci_controller *ctrlr, enum ufshci_attributes attr_type, uint8_t index, uint8_t selector, uint64_t value) @@ -270,7 +333,7 @@ ufshci_dev_init_uic_power_mode(struct ufshci_controller *ctrlr) */ const uint32_t fast_mode = 1; const uint32_t rx_bit_shift = 4; - const uint32_t power_mode = (fast_mode << rx_bit_shift) | fast_mode; + uint32_t power_mode, peer_granularity; /* Update lanes with available TX/RX lanes */ if (ufshci_uic_send_dme_get(ctrlr, PA_AvailTxDataLanes, @@ -295,6 +358,20 @@ ufshci_dev_init_uic_power_mode(struct ufshci_controller *ctrlr) ctrlr->rx_lanes)) return (ENXIO); + if (ctrlr->quirks & UFSHCI_QUIRK_CHANGE_LANE_AND_GEAR_SEPARATELY) { + /* Before changing gears, first change the number of lanes. */ + if (ufshci_uic_send_dme_get(ctrlr, PA_PWRMode, &power_mode)) + return (ENXIO); + if (ufshci_uic_send_dme_set(ctrlr, PA_PWRMode, power_mode)) + return (ENXIO); + + /* Wait for power mode changed. */ + if (ufshci_uic_power_mode_ready(ctrlr)) { + ufshci_reg_dump(ctrlr); + return (ENXIO); + } + } + /* Set HS-GEAR to max gear */ ctrlr->hs_gear = ctrlr->max_rx_hs_gear; if (ufshci_uic_send_dme_set(ctrlr, PA_TxGear, ctrlr->hs_gear)) @@ -346,6 +423,7 @@ ufshci_dev_init_uic_power_mode(struct ufshci_controller *ctrlr) return (ENXIO); /* Set TX/RX PWRMode */ + power_mode = (fast_mode << rx_bit_shift) | fast_mode; if (ufshci_uic_send_dme_set(ctrlr, PA_PWRMode, power_mode)) return (ENXIO); @@ -366,7 +444,8 @@ ufshci_dev_init_uic_power_mode(struct ufshci_controller *ctrlr) pause_sbt("ufshci", ustosbt(1250), 0, C_PREL(1)); /* Test with dme_peer_get to make sure there are no errors. */ - if (ufshci_uic_send_dme_peer_get(ctrlr, PA_Granularity, NULL)) + if (ufshci_uic_send_dme_peer_get(ctrlr, PA_Granularity, + &peer_granularity)) return (ENXIO); } @@ -398,7 +477,7 @@ ufshci_dev_get_descriptor(struct ufshci_controller *ctrlr) return (error); ver = be16toh(device->dev_desc.wSpecVersion); - ufshci_printf(ctrlr, "UFS device spec version %u.%u%u\n", + ufshci_printf(ctrlr, "UFS device spec version %u.%u.%u\n", UFSHCIV(UFSHCI_VER_REG_MJR, ver), UFSHCIV(UFSHCI_VER_REG_MNR, ver), UFSHCIV(UFSHCI_VER_REG_VS, ver)); ufshci_printf(ctrlr, "%u enabled LUNs found\n", @@ -426,3 +505,273 @@ ufshci_dev_get_descriptor(struct ufshci_controller *ctrlr) return (0); } + +static int +ufshci_dev_enable_write_booster(struct ufshci_controller *ctrlr) +{ + struct ufshci_device *dev = &ctrlr->ufs_dev; + int error; + + /* Enable WriteBooster */ + error = ufshci_dev_set_flag(ctrlr, UFSHCI_FLAG_F_WRITE_BOOSTER_EN); + if (error) { + ufshci_printf(ctrlr, "Failed to enable WriteBooster\n"); + return (error); + } + dev->is_wb_enabled = true; + + /* Enable WriteBooster buffer flush during hibernate */ + error = ufshci_dev_set_flag(ctrlr, + UFSHCI_FLAG_F_WB_BUFFER_FLUSH_DURING_HIBERNATE); + if (error) { + ufshci_printf(ctrlr, + "Failed to enable WriteBooster buffer flush during hibernate\n"); + return (error); + } + + /* Enable WriteBooster buffer flush */ + error = ufshci_dev_set_flag(ctrlr, UFSHCI_FLAG_F_WB_BUFFER_FLUSH_EN); + if (error) { + ufshci_printf(ctrlr, + "Failed to enable WriteBooster buffer flush\n"); + return (error); + } + dev->is_wb_flush_enabled = true; + + return (0); +} + +static int +ufshci_dev_disable_write_booster(struct ufshci_controller *ctrlr) +{ + struct ufshci_device *dev = &ctrlr->ufs_dev; + int error; + + /* Disable WriteBooster buffer flush */ + error = ufshci_dev_clear_flag(ctrlr, UFSHCI_FLAG_F_WB_BUFFER_FLUSH_EN); + if (error) { + ufshci_printf(ctrlr, + "Failed to disable WriteBooster buffer flush\n"); + return (error); + } + dev->is_wb_flush_enabled = false; + + /* Disable WriteBooster buffer flush during hibernate */ + error = ufshci_dev_clear_flag(ctrlr, + UFSHCI_FLAG_F_WB_BUFFER_FLUSH_DURING_HIBERNATE); + if (error) { + ufshci_printf(ctrlr, + "Failed to disable WriteBooster buffer flush during hibernate\n"); + return (error); + } + + /* Disable WriteBooster */ + error = ufshci_dev_clear_flag(ctrlr, UFSHCI_FLAG_F_WRITE_BOOSTER_EN); + if (error) { + ufshci_printf(ctrlr, "Failed to disable WriteBooster\n"); + return (error); + } + dev->is_wb_enabled = false; + + return (0); +} + +static int +ufshci_dev_is_write_booster_buffer_life_time_left( + struct ufshci_controller *ctrlr, bool *is_life_time_left) +{ + struct ufshci_device *dev = &ctrlr->ufs_dev; + uint8_t buffer_lun; + uint64_t life_time; + uint32_t error; + + if (dev->wb_buffer_type == UFSHCI_DESC_WB_BUF_TYPE_LU_DEDICATED) + buffer_lun = dev->wb_dedicated_lu; + else + buffer_lun = 0; + + error = ufshci_dev_read_attribute(ctrlr, + UFSHCI_ATTR_B_WB_BUFFER_LIFE_TIME_EST, buffer_lun, 0, &life_time); + if (error) + return (error); + + *is_life_time_left = (life_time != UFSHCI_ATTR_WB_LIFE_EXCEEDED); + + return (0); +} + +/* + * This function is not yet in use. It will be used when suspend/resume is + * implemented. + */ +static __unused int +ufshci_dev_need_write_booster_buffer_flush(struct ufshci_controller *ctrlr, + bool *need_flush) +{ + struct ufshci_device *dev = &ctrlr->ufs_dev; + bool is_life_time_left = false; + uint64_t available_buffer_size, current_buffer_size; + uint8_t buffer_lun; + uint32_t error; + + *need_flush = false; + + if (!dev->is_wb_enabled) + return (0); + + error = ufshci_dev_is_write_booster_buffer_life_time_left(ctrlr, + &is_life_time_left); + if (error) + return (error); + + if (!is_life_time_left) + return (ufshci_dev_disable_write_booster(ctrlr)); + + if (dev->wb_buffer_type == UFSHCI_DESC_WB_BUF_TYPE_LU_DEDICATED) + buffer_lun = dev->wb_dedicated_lu; + else + buffer_lun = 0; + + error = ufshci_dev_read_attribute(ctrlr, + UFSHCI_ATTR_B_AVAILABLE_WB_BUFFER_SIZE, buffer_lun, 0, + &available_buffer_size); + if (error) + return (error); + + switch (dev->wb_user_space_config_option) { + case UFSHCI_DESC_WB_BUF_USER_SPACE_REDUCTION: + *need_flush = (available_buffer_size <= + UFSHCI_ATTR_WB_AVAILABLE_10); + break; + case UFSHCI_DESC_WB_BUF_PRESERVE_USER_SPACE: + /* + * In PRESERVE USER SPACE mode, flush should be performed when + * the current buffer is greater than 0 and the available buffer + * below write_booster_flush_threshold is left. + */ + error = ufshci_dev_read_attribute(ctrlr, + UFSHCI_ATTR_D_CURRENT_WB_BUFFER_SIZE, buffer_lun, 0, + ¤t_buffer_size); + if (error) + return (error); + + if (current_buffer_size == 0) + return (0); + + *need_flush = (available_buffer_size < + dev->write_booster_flush_threshold); + break; + default: + ufshci_printf(ctrlr, + "Invalid bWriteBoosterBufferPreserveUserSpaceEn value"); + return (EINVAL); + } + + /* + * TODO: Need to handle WRITEBOOSTER_FLUSH_NEEDED exception case from + * wExceptionEventStatus attribute. + */ + + return (0); +} + +int +ufshci_dev_config_write_booster(struct ufshci_controller *ctrlr) +{ + struct ufshci_device *dev = &ctrlr->ufs_dev; + uint32_t extended_ufs_feature_support; + uint32_t alloc_units; + struct ufshci_unit_descriptor unit_desc; + uint8_t lun; + bool is_life_time_left; + uint32_t mega_byte = 1024 * 1024; + uint32_t error = 0; + + extended_ufs_feature_support = be32toh( + dev->dev_desc.dExtendedUfsFeaturesSupport); + if (!(extended_ufs_feature_support & + UFSHCI_DESC_EXT_UFS_FEATURE_WRITE_BOOSTER)) { + /* This device does not support Write Booster */ + return (0); + } + + if (ufshci_dev_enable_write_booster(ctrlr)) + return (0); + + /* Get WriteBooster buffer parameters */ + dev->wb_buffer_type = dev->dev_desc.bWriteBoosterBufferType; + dev->wb_user_space_config_option = + dev->dev_desc.bWriteBoosterBufferPreserveUserSpaceEn; + + /* + * Find the size of the write buffer. + * With LU-dedicated (00h), the WriteBooster buffer is assigned + * exclusively to one chosen LU (not one-per-LU), whereas Shared (01h) + * uses a single device-wide buffer shared by multiple LUs. + */ + if (dev->wb_buffer_type == UFSHCI_DESC_WB_BUF_TYPE_SINGLE_SHARED) { + alloc_units = be32toh( + dev->dev_desc.dNumSharedWriteBoosterBufferAllocUnits); + ufshci_printf(ctrlr, + "WriteBooster buffer type = Shared, alloc_units=%d\n", + alloc_units); + } else if (dev->wb_buffer_type == + UFSHCI_DESC_WB_BUF_TYPE_LU_DEDICATED) { + ufshci_printf(ctrlr, "WriteBooster buffer type = Dedicated\n"); + for (lun = 0; lun < ctrlr->max_lun_count; lun++) { + /* Find a dedicated buffer using a unit descriptor */ + if (ufshci_dev_read_unit_descriptor(ctrlr, lun, + &unit_desc)) + continue; + + alloc_units = be32toh( + unit_desc.dLUNumWriteBoosterBufferAllocUnits); + if (alloc_units) { + dev->wb_dedicated_lu = lun; + break; + } + } + } else { + ufshci_printf(ctrlr, + "Not supported WriteBooster buffer type: 0x%x\n", + dev->wb_buffer_type); + goto out; + } + + if (alloc_units == 0) { + ufshci_printf(ctrlr, "The WriteBooster buffer size is zero\n"); + goto out; + } + + dev->wb_buffer_size_mb = alloc_units * + dev->geo_desc.bAllocationUnitSize * + (be32toh(dev->geo_desc.dSegmentSize)) / + (mega_byte / UFSHCI_SECTOR_SIZE); + + /* Set to flush when 40% of the available buffer size remains */ + dev->write_booster_flush_threshold = UFSHCI_ATTR_WB_AVAILABLE_40; + + /* + * Check if WriteBooster Buffer lifetime is left. + * WriteBooster Buffer lifetime — percent of life used based on P/E + * cycles. If "preserve user space" is enabled, writes to normal user + * space also consume WB life since the area is shared. + */ + error = ufshci_dev_is_write_booster_buffer_life_time_left(ctrlr, + &is_life_time_left); + if (error) + goto out; + + if (!is_life_time_left) { + ufshci_printf(ctrlr, + "There is no WriteBooster buffer life time left.\n"); + goto out; + } + + ufshci_printf(ctrlr, "WriteBooster Enabled\n"); + return (0); +out: + ufshci_dev_disable_write_booster(ctrlr); + return (error); +} + diff --git a/sys/dev/ufshci/ufshci_pci.c b/sys/dev/ufshci/ufshci_pci.c index 65a69ee0b518..d64b7526f713 100644 --- a/sys/dev/ufshci/ufshci_pci.c +++ b/sys/dev/ufshci/ufshci_pci.c @@ -53,7 +53,8 @@ static struct _pcsid { { 0x98fa8086, "Intel Lakefield UFS Host Controller", UFSHCI_REF_CLK_19_2MHz, UFSHCI_QUIRK_LONG_PEER_PA_TACTIVATE | - UFSHCI_QUIRK_WAIT_AFTER_POWER_MODE_CHANGE }, + UFSHCI_QUIRK_WAIT_AFTER_POWER_MODE_CHANGE | + UFSHCI_QUIRK_CHANGE_LANE_AND_GEAR_SEPARATELY }, { 0x54ff8086, "Intel UFS Host Controller", UFSHCI_REF_CLK_19_2MHz }, { 0x00000000, NULL } }; diff --git a/sys/dev/ufshci/ufshci_private.h b/sys/dev/ufshci/ufshci_private.h index 1a2742ae2e80..2e033f84c373 100644 --- a/sys/dev/ufshci/ufshci_private.h +++ b/sys/dev/ufshci/ufshci_private.h @@ -46,6 +46,8 @@ MALLOC_DECLARE(M_UFSHCI); #define UFSHCI_UTR_ENTRIES (32) #define UFSHCI_UTRM_ENTRIES (8) +#define UFSHCI_SECTOR_SIZE (512) + struct ufshci_controller; struct ufshci_completion_poll_status { @@ -214,6 +216,15 @@ struct ufshci_device { struct ufshci_geometry_descriptor geo_desc; uint32_t unipro_version; + + /* WriteBooster */ + bool is_wb_enabled; + bool is_wb_flush_enabled; + uint32_t wb_buffer_type; + uint32_t wb_buffer_size_mb; + uint32_t wb_user_space_config_option; + uint8_t wb_dedicated_lu; + uint32_t write_booster_flush_threshold; }; /* @@ -229,7 +240,8 @@ struct ufshci_controller { 2 /* Need an additional 200 ms of PA_TActivate */ #define UFSHCI_QUIRK_WAIT_AFTER_POWER_MODE_CHANGE \ 4 /* Need to wait 1250us after power mode change */ - +#define UFSHCI_QUIRK_CHANGE_LANE_AND_GEAR_SEPARATELY \ + 8 /* Need to change the number of lanes before changing HS-GEAR. */ uint32_t ref_clk; struct cam_sim *ufshci_sim; @@ -356,6 +368,7 @@ int ufshci_dev_init_unipro(struct ufshci_controller *ctrlr); int ufshci_dev_init_uic_power_mode(struct ufshci_controller *ctrlr); int ufshci_dev_init_ufs_power_mode(struct ufshci_controller *ctrlr); int ufshci_dev_get_descriptor(struct ufshci_controller *ctrlr); +int ufshci_dev_config_write_booster(struct ufshci_controller *ctrlr); /* Controller Command */ void ufshci_ctrlr_cmd_send_task_mgmt_request(struct ufshci_controller *ctrlr, diff --git a/sys/dev/ufshci/ufshci_reg.h b/sys/dev/ufshci/ufshci_reg.h index 6c9b3e2c8c04..6d5768505102 100644 --- a/sys/dev/ufshci/ufshci_reg.h +++ b/sys/dev/ufshci/ufshci_reg.h @@ -274,7 +274,7 @@ struct ufshci_registers { #define UFSHCI_HCS_REG_UTMRLRDY_MASK (0x1) #define UFSHCI_HCS_REG_UCRDY_SHIFT (3) #define UFSHCI_HCS_REG_UCRDY_MASK (0x1) -#define UFSHCI_HCS_REG_UPMCRS_SHIFT (7) +#define UFSHCI_HCS_REG_UPMCRS_SHIFT (8) #define UFSHCI_HCS_REG_UPMCRS_MASK (0x7) #define UFSHCI_HCS_REG_UTPEC_SHIFT (12) #define UFSHCI_HCS_REG_UTPEC_MASK (0xF) diff --git a/sys/dev/ufshci/ufshci_sysctl.c b/sys/dev/ufshci/ufshci_sysctl.c index 5e5069f12e5f..56bc06b13f3c 100644 --- a/sys/dev/ufshci/ufshci_sysctl.c +++ b/sys/dev/ufshci/ufshci_sysctl.c @@ -152,6 +152,7 @@ ufshci_sysctl_initialize_ctrlr(struct ufshci_controller *ctrlr) struct sysctl_ctx_list *ctrlr_ctx; struct sysctl_oid *ctrlr_tree, *que_tree, *ioq_tree; struct sysctl_oid_list *ctrlr_list, *ioq_list; + struct ufshci_device *dev = &ctrlr->ufs_dev; #define QUEUE_NAME_LENGTH 16 char queue_name[QUEUE_NAME_LENGTH]; int i; @@ -177,6 +178,25 @@ ufshci_sysctl_initialize_ctrlr(struct ufshci_controller *ctrlr) SYSCTL_ADD_UINT(ctrlr_ctx, ctrlr_list, OID_AUTO, "cap", CTLFLAG_RD, &ctrlr->cap, 0, "Number of I/O queue pairs"); + SYSCTL_ADD_BOOL(ctrlr_ctx, ctrlr_list, OID_AUTO, "wb_enabled", + CTLFLAG_RD, &dev->is_wb_enabled, 0, "WriteBooster enable/disable"); + + SYSCTL_ADD_BOOL(ctrlr_ctx, ctrlr_list, OID_AUTO, "wb_flush_enabled", + CTLFLAG_RD, &dev->is_wb_flush_enabled, 0, + "WriteBooster flush enable/disable"); + + SYSCTL_ADD_UINT(ctrlr_ctx, ctrlr_list, OID_AUTO, "wb_buffer_type", + CTLFLAG_RD, &dev->wb_buffer_type, 0, "WriteBooster type"); + + SYSCTL_ADD_UINT(ctrlr_ctx, ctrlr_list, OID_AUTO, "wb_buffer_size_mb", + CTLFLAG_RD, &dev->wb_buffer_size_mb, 0, + "WriteBooster buffer size in MB"); + + SYSCTL_ADD_UINT(ctrlr_ctx, ctrlr_list, OID_AUTO, + "wb_user_space_config_option", CTLFLAG_RD, + &dev->wb_user_space_config_option, 0, + "WriteBooster preserve user space mode"); + SYSCTL_ADD_PROC(ctrlr_ctx, ctrlr_list, OID_AUTO, "timeout_period", CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_MPSAFE, &ctrlr->timeout_period, 0, ufshci_sysctl_timeout_period, "IU", diff --git a/sys/dev/ufshci/ufshci_uic_cmd.c b/sys/dev/ufshci/ufshci_uic_cmd.c index 2c5f635dc11e..b9c867ff7065 100644 --- a/sys/dev/ufshci/ufshci_uic_cmd.c +++ b/sys/dev/ufshci/ufshci_uic_cmd.c @@ -14,7 +14,7 @@ int ufshci_uic_power_mode_ready(struct ufshci_controller *ctrlr) { - uint32_t is; + uint32_t is, hcs; int timeout; /* Wait for the IS flag to change */ @@ -40,6 +40,15 @@ ufshci_uic_power_mode_ready(struct ufshci_controller *ctrlr) DELAY(10); } + /* Check HCS power mode change request status */ + hcs = ufshci_mmio_read_4(ctrlr, hcs); + if (UFSHCIV(UFSHCI_HCS_REG_UPMCRS, hcs) != 0x01) { + ufshci_printf(ctrlr, + "Power mode change request status error: 0x%x\n", + UFSHCIV(UFSHCI_HCS_REG_UPMCRS, hcs)); + return (ENXIO); + } + return (0); } @@ -112,6 +121,7 @@ ufshci_uic_send_cmd(struct ufshci_controller *ctrlr, struct ufshci_uic_cmd *uic_cmd, uint32_t *return_value) { int error; + uint32_t config_result_code; mtx_lock(&ctrlr->uic_cmd_lock); @@ -134,6 +144,13 @@ ufshci_uic_send_cmd(struct ufshci_controller *ctrlr, if (error) return (ENXIO); + config_result_code = ufshci_mmio_read_4(ctrlr, ucmdarg2); + if (config_result_code) { + ufshci_printf(ctrlr, + "Failed to send UIC command. (config result code = 0x%x)\n", + config_result_code); + } + if (return_value != NULL) *return_value = ufshci_mmio_read_4(ctrlr, ucmdarg3); diff --git a/sys/dev/usb/controller/xhci.c b/sys/dev/usb/controller/xhci.c index 5be592512196..788b2b718062 100644 --- a/sys/dev/usb/controller/xhci.c +++ b/sys/dev/usb/controller/xhci.c @@ -156,6 +156,7 @@ struct xhci_std_temp { static void xhci_do_poll(struct usb_bus *); static void xhci_device_done(struct usb_xfer *, usb_error_t); +static void xhci_get_xecp(struct xhci_softc *); static void xhci_root_intr(struct xhci_softc *); static void xhci_free_device_ext(struct usb_device *); static struct xhci_endpoint_ext *xhci_get_endpoint_ext(struct usb_device *, @@ -566,6 +567,8 @@ xhci_init(struct xhci_softc *sc, device_t self, uint8_t dma32) device_printf(self, "%d bytes context size, %d-bit DMA\n", sc->sc_ctx_is_64_byte ? 64 : 32, (int)sc->sc_bus.dma_bits); + xhci_get_xecp(sc); + /* enable 64Kbyte control endpoint quirk */ sc->sc_bus.control_ep_quirk = (xhcictlquirk ? 1 : 0); @@ -654,6 +657,88 @@ xhci_uninit(struct xhci_softc *sc) } static void +xhci_get_xecp(struct xhci_softc *sc) +{ + + uint32_t hccp1; + uint32_t eec; + uint32_t eecp; + bool first = true; + + hccp1 = XREAD4(sc, capa, XHCI_HCSPARAMS0); + + if (XHCI_HCS0_XECP(hccp1) == 0) { + device_printf(sc->sc_bus.parent, + "xECP: no capabilities found\n"); + return; + } + + /* + * Parse the xECP Capabilities table and print known caps. + * Implemented, vendor and reserved xECP Capabilities values are + * documented in Table 7.2 of eXtensible Host Controller Interface for + * Universal Serial Bus (xHCI) Rev 1.2b 2023. + */ + device_printf(sc->sc_bus.parent, "xECP capabilities <"); + + eec = -1; + for (eecp = XHCI_HCS0_XECP(hccp1) << 2; + eecp != 0 && XHCI_XECP_NEXT(eec) != 0; + eecp += XHCI_XECP_NEXT(eec) << 2) { + eec = XREAD4(sc, capa, eecp); + + uint8_t xecpid = XHCI_XECP_ID(eec); + + if ((xecpid >= 11 && xecpid <= 16) || + (xecpid >= 19 && xecpid <= 191)) { + if (!first) + printf(","); + printf("RES(%x)", xecpid); + } else if (xecpid > 191) { + if (!first) + printf(","); + printf("VEND(%x)", xecpid); + } else { + if (!first) + printf(","); + switch (xecpid) + { + case XHCI_ID_USB_LEGACY: + printf("LEGACY"); + break; + case XHCI_ID_PROTOCOLS: + printf("PROTO"); + break; + case XHCI_ID_POWER_MGMT: + printf("POWER"); + break; + case XHCI_ID_VIRTUALIZATION: + printf("VIRT"); + break; + case XHCI_ID_MSG_IRQ: + printf("MSG IRQ"); + break; + case XHCI_ID_USB_LOCAL_MEM: + printf("LOCAL MEM"); + break; + case XHCI_ID_USB_DEBUG: + printf("DEBUG"); + break; + case XHCI_ID_EXT_MSI: + printf("EXT MSI"); + break; + case XHCI_ID_USB3_TUN: + printf("TUN"); + break; + + } + } + first = false; + } + printf(">\n"); +} + +static void xhci_set_hw_power_sleep(struct usb_bus *bus, uint32_t state) { struct xhci_softc *sc = XHCI_BUS2SC(bus); diff --git a/sys/dev/usb/controller/xhcireg.h b/sys/dev/usb/controller/xhcireg.h index 9d0b6e2f4b4b..821897155544 100644 --- a/sys/dev/usb/controller/xhcireg.h +++ b/sys/dev/usb/controller/xhcireg.h @@ -205,6 +205,11 @@ #define XHCI_ID_VIRTUALIZATION 0x0004 #define XHCI_ID_MSG_IRQ 0x0005 #define XHCI_ID_USB_LOCAL_MEM 0x0006 +/* values 7-9 are reserved */ +#define XHCI_ID_USB_DEBUG 0x000a +/* values 11-16 are reserved */ +#define XHCI_ID_EXT_MSI 0x0011 +#define XHCI_ID_USB3_TUN 0x0012 /* XHCI register R/W wrappers */ #define XREAD1(sc, what, a) \ diff --git a/sys/fs/tarfs/tarfs_vnops.c b/sys/fs/tarfs/tarfs_vnops.c index acf18de5ab51..c110107bb210 100644 --- a/sys/fs/tarfs/tarfs_vnops.c +++ b/sys/fs/tarfs/tarfs_vnops.c @@ -334,6 +334,10 @@ tarfs_readdir(struct vop_readdir_args *ap) tnp, tnp->name, uio->uio_offset, uio->uio_resid); if (uio->uio_offset == TARFS_COOKIE_EOF) { + if (eofflag != NULL) { + TARFS_DPF(VNODE, "%s: Setting EOF flag\n", __func__); + *eofflag = 1; + } TARFS_DPF(VNODE, "%s: EOF\n", __func__); return (0); } diff --git a/sys/kern/kern_thread.c b/sys/kern/kern_thread.c index 50b040132396..3180c66cb42b 100644 --- a/sys/kern/kern_thread.c +++ b/sys/kern/kern_thread.c @@ -1694,8 +1694,10 @@ thread_single_end(struct proc *p, int mode) thread_unlock(td); } } - KASSERT(mode != SINGLE_BOUNDARY || p->p_boundary_count == 0, - ("inconsistent boundary count %d", p->p_boundary_count)); + KASSERT(mode != SINGLE_BOUNDARY || P_SHOULDSTOP(p) || + p->p_boundary_count == 0, + ("pid %d proc %p flags %#x inconsistent boundary count %d", + p->p_pid, p, p->p_flag, p->p_boundary_count)); PROC_SUNLOCK(p); wakeup(&p->p_flag); } diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c index a6e38be89291..57732ddab7d9 100644 --- a/sys/kern/vfs_subr.c +++ b/sys/kern/vfs_subr.c @@ -2186,6 +2186,8 @@ freevnode(struct vnode *vp) { struct bufobj *bo; + ASSERT_VOP_UNLOCKED(vp, __func__); + /* * The vnode has been marked for destruction, so free it. * @@ -2222,12 +2224,16 @@ freevnode(struct vnode *vp) mac_vnode_destroy(vp); #endif if (vp->v_pollinfo != NULL) { + int error __diagused; + /* * Use LK_NOWAIT to shut up witness about the lock. We may get * here while having another vnode locked when trying to * satisfy a lookup and needing to recycle. */ - VOP_LOCK(vp, LK_EXCLUSIVE | LK_NOWAIT); + error = VOP_LOCK(vp, LK_EXCLUSIVE | LK_NOWAIT); + VNASSERT(error == 0, vp, + ("freevnode: cannot lock vp %p for pollinfo destroy", vp)); destroy_vpollinfo(vp->v_pollinfo); VOP_UNLOCK(vp); vp->v_pollinfo = NULL; diff --git a/sys/net/if_bridge.c b/sys/net/if_bridge.c index 66555fd1feb5..a854bbb96394 100644 --- a/sys/net/if_bridge.c +++ b/sys/net/if_bridge.c @@ -1447,10 +1447,10 @@ bridge_ioctl_add(struct bridge_softc *sc, void *arg) #endif /* - * If member_ifaddrs is disabled, do not allow an interface with - * assigned IP addresses to be added to a bridge. + * If member_ifaddrs is disabled, do not allow an Ethernet-like + * interface with assigned IP addresses to be added to a bridge. */ - if (!V_member_ifaddrs) { + if (!V_member_ifaddrs && ifs->if_type != IFT_GIF) { struct ifaddr *ifa; CK_STAILQ_FOREACH(ifa, &ifs->if_addrhead, ifa_link) { diff --git a/sys/net/if_epair.c b/sys/net/if_epair.c index 581c2434b8fb..fbffa8f359a0 100644 --- a/sys/net/if_epair.c +++ b/sys/net/if_epair.c @@ -69,6 +69,7 @@ #include <net/if_media.h> #include <net/if_private.h> #include <net/if_types.h> +#include <net/if_vlan_var.h> #include <net/netisr.h> #ifdef RSS #include <net/rss_config.h> @@ -434,6 +435,21 @@ epair_media_status(struct ifnet *ifp __unused, struct ifmediareq *imr) imr->ifm_active = IFM_ETHER | IFM_10G_T | IFM_FDX; } +/* + * Update ifp->if_hwassist according to the current value of ifp->if_capenable. + */ +static void +epair_caps_changed(struct ifnet *ifp) +{ + uint64_t hwassist = 0; + + if (ifp->if_capenable & IFCAP_TXCSUM) + hwassist |= CSUM_IP_TCP | CSUM_IP_UDP; + if (ifp->if_capenable & IFCAP_TXCSUM_IPV6) + hwassist |= CSUM_IP6_TCP | CSUM_IP6_UDP; + ifp->if_hwassist = hwassist; +} + static int epair_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) { @@ -461,6 +477,44 @@ epair_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) error = 0; break; + case SIOCGIFCAP: + ifr->ifr_reqcap = ifp->if_capabilities; + ifr->ifr_curcap = ifp->if_capenable; + error = 0; + break; + case SIOCSIFCAP: + /* + * Enable/disable capabilities as requested, besides + * IFCAP_RXCSUM(_IPV6), which always remain enabled. + * Incoming packets may have the mbuf flag CSUM_DATA_VALID set. + * Without IFCAP_RXCSUM(_IPV6), this flag would have to be + * removed, which does not seem helpful. + */ + ifp->if_capenable = ifr->ifr_reqcap | IFCAP_RXCSUM | + IFCAP_RXCSUM_IPV6; + epair_caps_changed(ifp); + /* + * If IFCAP_TXCSUM(_IPV6) has been changed, change it on the + * other epair interface as well. + * A bridge disables IFCAP_TXCSUM(_IPV6) when adding one epair + * interface if another interface in the bridge has it disabled. + * In that case this capability needs to be disabled on the + * other epair interface to avoid sending packets in the bridge + * that rely on this capability. + */ + sc = ifp->if_softc; + if ((ifp->if_capenable ^ sc->oifp->if_capenable) & + (IFCAP_TXCSUM | IFCAP_TXCSUM_IPV6)) { + sc->oifp->if_capenable &= + ~(IFCAP_TXCSUM | IFCAP_TXCSUM_IPV6); + sc->oifp->if_capenable |= ifp->if_capenable & + (IFCAP_TXCSUM | IFCAP_TXCSUM_IPV6); + epair_caps_changed(sc->oifp); + } + VLAN_CAPABILITIES(ifp); + error = 0; + break; + default: /* Let the common ethernet handler process this. */ error = ether_ioctl(ifp, cmd, data); @@ -572,8 +626,11 @@ epair_setup_ifp(struct epair_softc *sc, char *name, int unit) ifp->if_dname = epairname; ifp->if_dunit = unit; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; - ifp->if_capabilities = IFCAP_VLAN_MTU; - ifp->if_capenable = IFCAP_VLAN_MTU; + ifp->if_capabilities = IFCAP_VLAN_MTU | IFCAP_TXCSUM | + IFCAP_TXCSUM_IPV6 | IFCAP_RXCSUM | IFCAP_RXCSUM_IPV6; + ifp->if_capenable = IFCAP_VLAN_MTU | IFCAP_TXCSUM | + IFCAP_TXCSUM_IPV6 | IFCAP_RXCSUM | IFCAP_RXCSUM_IPV6; + epair_caps_changed(ifp); ifp->if_transmit = epair_transmit; ifp->if_qflush = epair_qflush; ifp->if_start = epair_start; diff --git a/sys/net/iflib.c b/sys/net/iflib.c index 98c59e5de988..308ecad0a846 100644 --- a/sys/net/iflib.c +++ b/sys/net/iflib.c @@ -712,7 +712,7 @@ static uint32_t iflib_txq_can_drain(struct ifmp_ring *); static void iflib_altq_if_start(if_t ifp); static int iflib_altq_if_transmit(if_t ifp, struct mbuf *m); #endif -static int iflib_register(if_ctx_t); +static void iflib_register(if_ctx_t); static void iflib_deregister(if_ctx_t); static void iflib_unregister_vlan_handlers(if_ctx_t ctx); static uint16_t iflib_get_mbuf_size_for(unsigned int size); @@ -5136,10 +5136,7 @@ iflib_device_register(device_t dev, void *sc, if_shared_ctx_t sctx, if_ctx_t *ct ctx->ifc_dev = dev; ctx->ifc_softc = sc; - if ((err = iflib_register(ctx)) != 0) { - device_printf(dev, "iflib_register failed %d\n", err); - goto fail_ctx_free; - } + iflib_register(ctx); iflib_add_device_sysctl_pre(ctx); scctx = &ctx->ifc_softc_ctx; @@ -5363,7 +5360,6 @@ iflib_device_register(device_t dev, void *sc, if_shared_ctx_t sctx, if_ctx_t *ct DEBUGNET_SET(ctx->ifc_ifp, iflib); - if_setgetcounterfn(ctx->ifc_ifp, iflib_if_get_counter); iflib_add_device_sysctl_post(ctx); iflib_add_pfil(ctx); ctx->ifc_flags |= IFC_INIT_DONE; @@ -5387,7 +5383,6 @@ fail_unlock: CTX_UNLOCK(ctx); IFNET_WUNLOCK(); iflib_deregister(ctx); -fail_ctx_free: device_set_softc(ctx->ifc_dev, NULL); if (ctx->ifc_flags & IFC_SC_ALLOCATED) free(ctx->ifc_softc, M_IFLIB); @@ -5685,7 +5680,7 @@ _iflib_pre_assert(if_softc_ctx_t scctx) MPASS(scctx->isc_txrx->ift_rxd_flush); } -static int +static void iflib_register(if_ctx_t ctx) { if_shared_ctx_t sctx = ctx->ifc_sctx; @@ -5718,6 +5713,7 @@ iflib_register(if_ctx_t ctx) if_settransmitfn(ifp, iflib_if_transmit); #endif if_setqflushfn(ifp, iflib_if_qflush); + if_setgetcounterfn(ifp, iflib_if_get_counter); if_setflags(ifp, IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST); ctx->ifc_vlan_attach_event = EVENTHANDLER_REGISTER(vlan_config, iflib_vlan_register, ctx, @@ -5731,7 +5727,6 @@ iflib_register(if_ctx_t ctx) ifmedia_init(ctx->ifc_mediap, IFM_IMASK, iflib_media_change, iflib_media_status); } - return (0); } static void diff --git a/sys/net80211/ieee80211_ddb.c b/sys/net80211/ieee80211_ddb.c index d96d7988a864..1dd8e38b9896 100644 --- a/sys/net80211/ieee80211_ddb.c +++ b/sys/net80211/ieee80211_ddb.c @@ -296,7 +296,7 @@ _db_show_sta(const struct ieee80211_node *ni) ni->ni_htparam, ni->ni_htctlchan, ni->ni_ht2ndchan); db_printf("\thtopmode 0x%x htstbc 0x%x chw %d (%s)\n", ni->ni_htopmode, ni->ni_htstbc, - ni->ni_chw, ieee80211_ni_chw_to_str(ni->ni_chw)); + ni->ni_chw, net80211_ni_chw_to_str(ni->ni_chw)); /* XXX ampdu state */ for (i = 0; i < WME_NUM_TID; i++) diff --git a/sys/net80211/ieee80211_freebsd.h b/sys/net80211/ieee80211_freebsd.h index 3684fba52c5c..954801d95787 100644 --- a/sys/net80211/ieee80211_freebsd.h +++ b/sys/net80211/ieee80211_freebsd.h @@ -341,11 +341,16 @@ struct mbuf *ieee80211_getmgtframe(uint8_t **frm, int headroom, int pktlen); #define M_AGE_SUB(m,adj) (m->m_pkthdr.csum_data -= adj) /* - * Store the sequence number. + * Store / retrieve the sequence number in an mbuf. + * + * The sequence number being stored/retreived is the 12 bit + * base sequence number, not the 16 bit sequence number field. + * I.e., it's from 0..4095 inclusive, with no 4 bit padding for + * fragment numbers. */ #define M_SEQNO_SET(m, seqno) \ - ((m)->m_pkthdr.tso_segsz = (seqno)) -#define M_SEQNO_GET(m) ((m)->m_pkthdr.tso_segsz) + ((m)->m_pkthdr.tso_segsz = ((seqno) % IEEE80211_SEQ_RANGE)) +#define M_SEQNO_GET(m) (((m)->m_pkthdr.tso_segsz) % IEEE80211_SEQ_RANGE) #define MTAG_ABI_NET80211 1132948340 /* net80211 ABI */ diff --git a/sys/net80211/ieee80211_ht.c b/sys/net80211/ieee80211_ht.c index c28f124648a1..018927a6dad4 100644 --- a/sys/net80211/ieee80211_ht.c +++ b/sys/net80211/ieee80211_ht.c @@ -1476,7 +1476,7 @@ ieee80211_ht_wds_init(struct ieee80211_node *ni) ni->ni_htcap |= IEEE80211_HTCAP_SHORTGI20; if (IEEE80211_IS_CHAN_HT40(ni->ni_chan)) { ni->ni_htcap |= IEEE80211_HTCAP_CHWIDTH40; - ni->ni_chw = IEEE80211_STA_RX_BW_40; + ni->ni_chw = NET80211_STA_RX_BW_40; if (IEEE80211_IS_CHAN_HT40U(ni->ni_chan)) ni->ni_ht2ndchan = IEEE80211_HTINFO_2NDCHAN_ABOVE; else if (IEEE80211_IS_CHAN_HT40D(ni->ni_chan)) @@ -1484,7 +1484,7 @@ ieee80211_ht_wds_init(struct ieee80211_node *ni) if (vap->iv_flags_ht & IEEE80211_FHT_SHORTGI40) ni->ni_htcap |= IEEE80211_HTCAP_SHORTGI40; } else { - ni->ni_chw = IEEE80211_STA_RX_BW_20; + ni->ni_chw = NET80211_STA_RX_BW_20; ni->ni_ht2ndchan = IEEE80211_HTINFO_2NDCHAN_NONE; } ni->ni_htctlchan = ni->ni_chan->ic_ieee; @@ -1580,7 +1580,7 @@ ieee80211_ht_node_join(struct ieee80211_node *ni) if (ni->ni_flags & IEEE80211_NODE_HT) { vap->iv_ht_sta_assoc++; - if (ni->ni_chw == IEEE80211_STA_RX_BW_40) + if (ni->ni_chw == NET80211_STA_RX_BW_40) vap->iv_ht40_sta_assoc++; } htinfo_update(vap); @@ -1598,7 +1598,7 @@ ieee80211_ht_node_leave(struct ieee80211_node *ni) if (ni->ni_flags & IEEE80211_NODE_HT) { vap->iv_ht_sta_assoc--; - if (ni->ni_chw == IEEE80211_STA_RX_BW_40) + if (ni->ni_chw == NET80211_STA_RX_BW_40) vap->iv_ht40_sta_assoc--; } htinfo_update(vap); @@ -1827,7 +1827,7 @@ htinfo_update_chw(struct ieee80211_node *ni, int htflags, int vhtflags) done: /* update node's (11n) tx channel width */ ni->ni_chw = IEEE80211_IS_CHAN_HT40(ni->ni_chan) ? - IEEE80211_STA_RX_BW_40 : IEEE80211_STA_RX_BW_20; + NET80211_STA_RX_BW_40 : NET80211_STA_RX_BW_20; return (ret); } @@ -2689,11 +2689,11 @@ ht_recv_action_ht_txchwidth(struct ieee80211_node *ni, * here. */ chw = (frm[2] == IEEE80211_A_HT_TXCHWIDTH_2040) ? - IEEE80211_STA_RX_BW_40 : IEEE80211_STA_RX_BW_20; + NET80211_STA_RX_BW_40 : NET80211_STA_RX_BW_20; IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_11N, ni, "%s: HT txchwidth, width %d%s (%s)", __func__, - chw, ni->ni_chw != chw ? "*" : "", ieee80211_ni_chw_to_str(chw)); + chw, ni->ni_chw != chw ? "*" : "", net80211_ni_chw_to_str(chw)); if (chw != ni->ni_chw) { /* XXX does this need to change the ht40 station count? */ ni->ni_chw = chw; @@ -3832,5 +3832,5 @@ ieee80211_ht_check_tx_ht40(const struct ieee80211_node *ni) return (IEEE80211_IS_CHAN_HT40(bss_chan) && IEEE80211_IS_CHAN_HT40(ni->ni_chan) && - (ni->ni_chw == IEEE80211_STA_RX_BW_40)); + (ni->ni_chw == NET80211_STA_RX_BW_40)); } diff --git a/sys/net80211/ieee80211_node.c b/sys/net80211/ieee80211_node.c index a201d1b278f0..49ba00299fee 100644 --- a/sys/net80211/ieee80211_node.c +++ b/sys/net80211/ieee80211_node.c @@ -2673,7 +2673,7 @@ ieee80211_dump_node(struct ieee80211_node_table *nt __unused, ni->ni_htctlchan, ni->ni_ht2ndchan); net80211_printf("\thtopmode %x htstbc %x htchw %d (%s)\n", ni->ni_htopmode, ni->ni_htstbc, - ni->ni_chw, ieee80211_ni_chw_to_str(ni->ni_chw)); + ni->ni_chw, net80211_ni_chw_to_str(ni->ni_chw)); net80211_printf("\tvhtcap %x freq1 %d freq2 %d vhtbasicmcs %x\n", ni->ni_vhtcap, (int) ni->ni_vht_chan1, (int) ni->ni_vht_chan2, (int) ni->ni_vht_basicmcs); @@ -2831,7 +2831,7 @@ ieee80211_node_join(struct ieee80211_node *ni, int resp) ni->ni_flags & IEEE80211_NODE_QOS ? ", QoS" : "", /* XXX update for VHT string */ ni->ni_flags & IEEE80211_NODE_HT ? - (ni->ni_chw == IEEE80211_STA_RX_BW_40 ? ", HT40" : ", HT20") : "", + (ni->ni_chw == NET80211_STA_RX_BW_40 ? ", HT40" : ", HT20") : "", ni->ni_flags & IEEE80211_NODE_AMPDU ? " (+AMPDU)" : "", ni->ni_flags & IEEE80211_NODE_AMSDU ? " (+AMSDU)" : "", ni->ni_flags & IEEE80211_NODE_MIMO_RTS ? " (+SMPS-DYN)" : diff --git a/sys/net80211/ieee80211_node.h b/sys/net80211/ieee80211_node.h index ef25fa0d7fdd..f1246dd12419 100644 --- a/sys/net80211/ieee80211_node.h +++ b/sys/net80211/ieee80211_node.h @@ -109,33 +109,33 @@ enum ieee80211_mesh_mlstate { "\20\1IDLE\2OPENSNT\2OPENRCV\3CONFIRMRCV\4ESTABLISHED\5HOLDING" /* - * This structure is shared with LinuxKPI 802.11 code describing up-to - * which channel width the station can receive. + * This enum was shared with the LinuxKPI enum ieee80211_sta_rx_bandwidth + * describing up-to which channel width the station can receive. * Rather than using hardcoded MHz values for the channel width use an enum with * flags. This allows us to keep the uint8_t slot for ni_chw in - * struct ieee80211_node and means we do not have to sync to the value for - * LinuxKPI. + * struct ieee80211_node it means we do not have to sync to the value for + * LinuxKPI (just the names). * * NB: BW_20 needs to 0 and values need to be sorted! Cannot make it * bitfield-alike for use with %b. */ -enum ieee80211_sta_rx_bw { - IEEE80211_STA_RX_BW_20 = 0x00, - IEEE80211_STA_RX_BW_40, - IEEE80211_STA_RX_BW_80, - IEEE80211_STA_RX_BW_160, - IEEE80211_STA_RX_BW_320, +enum net80211_sta_rx_bw { + NET80211_STA_RX_BW_20 = 0x00, + NET80211_STA_RX_BW_40, + NET80211_STA_RX_BW_80, + NET80211_STA_RX_BW_160, + NET80211_STA_RX_BW_320, } __packed; static inline const char * -ieee80211_ni_chw_to_str(enum ieee80211_sta_rx_bw bw) +net80211_ni_chw_to_str(enum net80211_sta_rx_bw bw) { switch (bw) { - case IEEE80211_STA_RX_BW_20: return ("BW_20"); - case IEEE80211_STA_RX_BW_40: return ("BW_40"); - case IEEE80211_STA_RX_BW_80: return ("BW_80"); - case IEEE80211_STA_RX_BW_160: return ("BW_160"); - case IEEE80211_STA_RX_BW_320: return ("BW_320"); + case NET80211_STA_RX_BW_20: return ("BW_20"); + case NET80211_STA_RX_BW_40: return ("BW_40"); + case NET80211_STA_RX_BW_80: return ("BW_80"); + case NET80211_STA_RX_BW_160: return ("BW_160"); + case NET80211_STA_RX_BW_320: return ("BW_320"); } } @@ -285,7 +285,7 @@ struct ieee80211_node { uint8_t ni_ht2ndchan; /* HT 2nd channel */ uint8_t ni_htopmode; /* HT operating mode */ uint8_t ni_htstbc; /* HT */ - enum ieee80211_sta_rx_bw ni_chw; /* negotiated channel width */ + enum net80211_sta_rx_bw ni_chw; /* negotiated channel width */ struct ieee80211_htrateset ni_htrates; /* negotiated ht rate set */ struct ieee80211_tx_ampdu ni_tx_ampdu[WME_NUM_TID]; struct ieee80211_rx_ampdu ni_rx_ampdu[WME_NUM_TID]; diff --git a/sys/net80211/ieee80211_phy.c b/sys/net80211/ieee80211_phy.c index eb96d74a2bd9..7f53c717152b 100644 --- a/sys/net80211/ieee80211_phy.c +++ b/sys/net80211/ieee80211_phy.c @@ -658,26 +658,26 @@ static uint16_t ieee80211_vht_mcs_allowed_list_160[] = { * * See 802.11-2020 21.5 (Parameters for VHT-MCSs) for more details. * - * @param bw channel bandwidth, via enum ieee80211_sta_rx_bw + * @param bw channel bandwidth, via enum net80211_sta_rx_bw * @param nss number of spatial streams, 1..8 * @returns bitmask of valid MCS rates from 0..9 */ uint16_t -ieee80211_phy_vht_get_mcs_mask(enum ieee80211_sta_rx_bw bw, uint8_t nss) +ieee80211_phy_vht_get_mcs_mask(enum net80211_sta_rx_bw bw, uint8_t nss) { if (nss == 0 || nss > 8) return (0); switch (bw) { - case IEEE80211_STA_RX_BW_20: + case NET80211_STA_RX_BW_20: return (ieee80211_vht_mcs_allowed_list_20[nss - 1]); - case IEEE80211_STA_RX_BW_40: + case NET80211_STA_RX_BW_40: return (ieee80211_vht_mcs_allowed_list_40[nss - 1]); - case IEEE80211_STA_RX_BW_80: + case NET80211_STA_RX_BW_80: return (ieee80211_vht_mcs_allowed_list_80[nss - 1]); - case IEEE80211_STA_RX_BW_160: + case NET80211_STA_RX_BW_160: return (ieee80211_vht_mcs_allowed_list_160[nss - 1]); - case IEEE80211_STA_RX_BW_320: + case NET80211_STA_RX_BW_320: /* invalid for VHT */ return (0); } @@ -689,14 +689,14 @@ ieee80211_phy_vht_get_mcs_mask(enum ieee80211_sta_rx_bw bw, uint8_t nss) * * See 802.11-2020 21.5 (Parameters for VHT-MCSs) for more details. * - * @param bw channel bandwidth, via enum ieee80211_sta_rx_bw + * @param bw channel bandwidth, via enum net80211_sta_rx_bw * @param nss number of spatial streams, 1..8 * @param mcs MCS rate, 0..9 * @retval true if the NSS / MCS / bandwidth combination is valid * @retval false if the NSS / MCS / bandwidth combination is not valid */ bool -ieee80211_phy_vht_validate_mcs(enum ieee80211_sta_rx_bw bw, uint8_t nss, +ieee80211_phy_vht_validate_mcs(enum net80211_sta_rx_bw bw, uint8_t nss, uint8_t mcs) { uint16_t mask; @@ -737,7 +737,7 @@ static struct mcs_entry mcs_entries[] = { /** * @brief Calculate the bitrate of the given VHT MCS rate. * - * @param bw Channel bandwidth (enum ieee80211_sta_rx_bw) + * @param bw Channel bandwidth (enum net80211_sta_rx_bw) * @param nss Number of spatial streams, 1..8 * @param mcs MCS, 0..9 * @param is_shortgi True if short guard-interval (400nS) @@ -746,7 +746,7 @@ static struct mcs_entry mcs_entries[] = { * @returns The bitrate in kbit/sec. */ uint32_t -ieee80211_phy_vht_get_mcs_kbit(enum ieee80211_sta_rx_bw bw, +ieee80211_phy_vht_get_mcs_kbit(enum net80211_sta_rx_bw bw, uint8_t nss, uint8_t mcs, bool is_shortgi) { uint32_t sym_len, n_carriers; @@ -773,16 +773,16 @@ ieee80211_phy_vht_get_mcs_kbit(enum ieee80211_sta_rx_bw bw, * See 802.11-2020 Table 21-5 (Timing-related constraints.) */ switch (bw) { - case IEEE80211_STA_RX_BW_20: + case NET80211_STA_RX_BW_20: n_carriers = 52; break; - case IEEE80211_STA_RX_BW_40: + case NET80211_STA_RX_BW_40: n_carriers = 108; break; - case IEEE80211_STA_RX_BW_80: + case NET80211_STA_RX_BW_80: n_carriers = 234; break; - case IEEE80211_STA_RX_BW_160: + case NET80211_STA_RX_BW_160: n_carriers = 468; break; default: diff --git a/sys/net80211/ieee80211_phy.h b/sys/net80211/ieee80211_phy.h index 749b082e34e9..391c8bfc5010 100644 --- a/sys/net80211/ieee80211_phy.h +++ b/sys/net80211/ieee80211_phy.h @@ -221,13 +221,13 @@ uint32_t ieee80211_compute_duration_ht(uint32_t frameLen, uint16_t rate, int streams, int isht40, int isShortGI); -enum ieee80211_sta_rx_bw; +enum net80211_sta_rx_bw; -uint16_t ieee80211_phy_vht_get_mcs_mask(enum ieee80211_sta_rx_bw, +uint16_t ieee80211_phy_vht_get_mcs_mask(enum net80211_sta_rx_bw, uint8_t); -bool ieee80211_phy_vht_validate_mcs(enum ieee80211_sta_rx_bw, +bool ieee80211_phy_vht_validate_mcs(enum net80211_sta_rx_bw, uint8_t, uint8_t); -uint32_t ieee80211_phy_vht_get_mcs_kbit(enum ieee80211_sta_rx_bw, +uint32_t ieee80211_phy_vht_get_mcs_kbit(enum net80211_sta_rx_bw, uint8_t, uint8_t, bool); #endif /* _KERNEL */ diff --git a/sys/net80211/ieee80211_sta.c b/sys/net80211/ieee80211_sta.c index 463a8b16773b..19e5ffe9a367 100644 --- a/sys/net80211/ieee80211_sta.c +++ b/sys/net80211/ieee80211_sta.c @@ -1934,7 +1934,7 @@ sta_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0, int subtype, vap->iv_flags&IEEE80211_F_USEPROT ? ", protection" : "", ni->ni_flags & IEEE80211_NODE_QOS ? ", QoS" : "", ni->ni_flags & IEEE80211_NODE_HT ? - (ni->ni_chw == IEEE80211_STA_RX_BW_40 ? ", HT40" : ", HT20") : "", + (ni->ni_chw == NET80211_STA_RX_BW_40 ? ", HT40" : ", HT20") : "", ni->ni_flags & IEEE80211_NODE_AMPDU ? " (+AMPDU)" : "", ni->ni_flags & IEEE80211_NODE_AMSDU ? " (+AMSDU)" : "", ni->ni_flags & IEEE80211_NODE_MIMO_RTS ? " (+SMPS-DYN)" : diff --git a/sys/net80211/ieee80211_vht.c b/sys/net80211/ieee80211_vht.c index de0b691d4d2a..10a5fc7f08ab 100644 --- a/sys/net80211/ieee80211_vht.c +++ b/sys/net80211/ieee80211_vht.c @@ -974,7 +974,7 @@ ieee80211_vht_check_tx_vht40(const struct ieee80211_node *ni) return (IEEE80211_IS_CHAN_VHT40(bss_chan) && IEEE80211_IS_CHAN_VHT40(ni->ni_chan) && - (ni->ni_chw == IEEE80211_STA_RX_BW_40)); + (ni->ni_chw == NET80211_STA_RX_BW_40)); } /* @@ -1003,7 +1003,7 @@ ieee80211_vht_check_tx_vht80(const struct ieee80211_node *ni) */ return (IEEE80211_IS_CHAN_VHT80(bss_chan) && IEEE80211_IS_CHAN_VHT80(ni->ni_chan) && - (ni->ni_chw != IEEE80211_STA_RX_BW_20)); + (ni->ni_chw != NET80211_STA_RX_BW_20)); } /* @@ -1030,7 +1030,7 @@ ieee80211_vht_check_tx_vht160(const struct ieee80211_node *ni) * If a HT TX width action frame sets it to 20MHz * then reject doing 160MHz. */ - if (ni->ni_chw == IEEE80211_STA_RX_BW_20) + if (ni->ni_chw == NET80211_STA_RX_BW_20) return (false); if (IEEE80211_IS_CHAN_VHT160(bss_chan) && @@ -1062,19 +1062,19 @@ ieee80211_vht_check_tx_vht160(const struct ieee80211_node *ni) */ bool ieee80211_vht_check_tx_bw(const struct ieee80211_node *ni, - enum ieee80211_sta_rx_bw bw) + enum net80211_sta_rx_bw bw) { switch (bw) { - case IEEE80211_STA_RX_BW_20: + case NET80211_STA_RX_BW_20: return (ieee80211_vht_check_tx_vht(ni)); - case IEEE80211_STA_RX_BW_40: + case NET80211_STA_RX_BW_40: return (ieee80211_vht_check_tx_vht40(ni)); - case IEEE80211_STA_RX_BW_80: + case NET80211_STA_RX_BW_80: return (ieee80211_vht_check_tx_vht80(ni)); - case IEEE80211_STA_RX_BW_160: + case NET80211_STA_RX_BW_160: return (ieee80211_vht_check_tx_vht160(ni)); - case IEEE80211_STA_RX_BW_320: + case NET80211_STA_RX_BW_320: return (false); default: return (false); @@ -1096,7 +1096,7 @@ ieee80211_vht_check_tx_bw(const struct ieee80211_node *ni, */ bool ieee80211_vht_node_check_tx_valid_mcs(const struct ieee80211_node *ni, - enum ieee80211_sta_rx_bw bw, uint8_t nss, uint8_t mcs) + enum net80211_sta_rx_bw bw, uint8_t nss, uint8_t mcs) { uint8_t mc; diff --git a/sys/net80211/ieee80211_vht.h b/sys/net80211/ieee80211_vht.h index a1529df4a85b..b9b19fbc6008 100644 --- a/sys/net80211/ieee80211_vht.h +++ b/sys/net80211/ieee80211_vht.h @@ -65,8 +65,8 @@ void ieee80211_vht_get_vhtinfo_ie(struct ieee80211_node *ni, bool ieee80211_vht_check_tx_vht(const struct ieee80211_node *); bool ieee80211_vht_check_tx_bw(const struct ieee80211_node *, - enum ieee80211_sta_rx_bw); + enum net80211_sta_rx_bw); bool ieee80211_vht_node_check_tx_valid_mcs(const struct ieee80211_node *, - enum ieee80211_sta_rx_bw bw, uint8_t, uint8_t); + enum net80211_sta_rx_bw bw, uint8_t, uint8_t); #endif /* _NET80211_IEEE80211_VHT_H_ */ diff --git a/sys/netgraph/ng_parse.c b/sys/netgraph/ng_parse.c index 448ecc92f075..5e1a1bb47ac0 100644 --- a/sys/netgraph/ng_parse.c +++ b/sys/netgraph/ng_parse.c @@ -1199,14 +1199,14 @@ ng_parse_composite(const struct ng_parse_type *type, const char *s, int *off, const u_char *const start, u_char *const buf, int *buflen, const enum comptype ctype) { - const int num = ng_get_composite_len(type, start, buf, ctype); int nextIndex = 0; /* next implicit array index */ u_int index; /* field or element index */ int *foff; /* field value offsets in string */ int align, len, blen, error = 0; /* Initialize */ - if (num < 0) + const int num = ng_get_composite_len(type, start, buf, ctype); + if (num < 0 || num > INT_MAX / sizeof(*foff)) return (EINVAL); foff = malloc(num * sizeof(*foff), M_NETGRAPH_PARSE, M_NOWAIT | M_ZERO); if (foff == NULL) { diff --git a/sys/netinet/in.c b/sys/netinet/in.c index 963449d4b4b1..0e283a7d099d 100644 --- a/sys/netinet/in.c +++ b/sys/netinet/in.c @@ -522,8 +522,8 @@ in_aifaddr_ioctl(u_long cmd, caddr_t data, struct ifnet *ifp, struct ucred *cred /* * Check if bridge wants to allow adding addrs to member interfaces. */ - if (ifp->if_bridge && bridge_member_ifaddrs_p && - !bridge_member_ifaddrs_p()) + if (ifp->if_bridge != NULL && ifp->if_type != IFT_GIF && + bridge_member_ifaddrs_p != NULL && !bridge_member_ifaddrs_p()) return (EINVAL); /* diff --git a/sys/netinet/tcp_syncache.c b/sys/netinet/tcp_syncache.c index d617d0ed4aac..1ee6c6e31f33 100644 --- a/sys/netinet/tcp_syncache.c +++ b/sys/netinet/tcp_syncache.c @@ -102,15 +102,15 @@ #include <security/mac/mac_framework.h> -VNET_DEFINE_STATIC(int, tcp_syncookies) = 1; +VNET_DEFINE_STATIC(bool, tcp_syncookies) = true; #define V_tcp_syncookies VNET(tcp_syncookies) -SYSCTL_INT(_net_inet_tcp, OID_AUTO, syncookies, CTLFLAG_VNET | CTLFLAG_RW, +SYSCTL_BOOL(_net_inet_tcp, OID_AUTO, syncookies, CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(tcp_syncookies), 0, "Use TCP SYN cookies if the syncache overflows"); -VNET_DEFINE_STATIC(int, tcp_syncookiesonly) = 0; +VNET_DEFINE_STATIC(bool, tcp_syncookiesonly) = false; #define V_tcp_syncookiesonly VNET(tcp_syncookiesonly) -SYSCTL_INT(_net_inet_tcp, OID_AUTO, syncookies_only, CTLFLAG_VNET | CTLFLAG_RW, +SYSCTL_BOOL(_net_inet_tcp, OID_AUTO, syncookies_only, CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(tcp_syncookiesonly), 0, "Use only TCP SYN cookies"); @@ -553,9 +553,8 @@ syncache_timer(void *xsch) static inline bool syncache_cookiesonly(void) { - - return (V_tcp_syncookies && (V_tcp_syncache.paused || - V_tcp_syncookiesonly)); + return ((V_tcp_syncookies && V_tcp_syncache.paused) || + V_tcp_syncookiesonly); } /* @@ -1083,40 +1082,48 @@ syncache_expand(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th, #endif if (sc == NULL) { - /* - * There is no syncache entry, so see if this ACK is - * a returning syncookie. To do this, first: - * A. Check if syncookies are used in case of syncache - * overflows - * B. See if this socket has had a syncache entry dropped in - * the recent past. We don't want to accept a bogus - * syncookie if we've never received a SYN or accept it - * twice. - * C. check that the syncookie is valid. If it is, then - * cobble up a fake syncache entry, and return. - */ - if (locked && !V_tcp_syncookies) { - SCH_UNLOCK(sch); - TCPSTAT_INC(tcps_sc_spurcookie); - if ((s = tcp_log_addrs(inc, th, NULL, NULL))) - log(LOG_DEBUG, "%s; %s: Spurious ACK, " - "segment rejected (syncookies disabled)\n", - s, __func__); - goto failed; - } - if (locked && !V_tcp_syncookiesonly && - sch->sch_last_overflow < time_uptime - SYNCOOKIE_LIFETIME) { + if (locked) { + /* + * The syncache is currently in use (neither disabled, + * nor paused), but no entry was found. + */ + if (!V_tcp_syncookies) { + /* + * Since no syncookies are used in case of + * a bucket overflow, don't even check for + * a valid syncookie. + */ + SCH_UNLOCK(sch); + TCPSTAT_INC(tcps_sc_spurcookie); + if ((s = tcp_log_addrs(inc, th, NULL, NULL))) + log(LOG_DEBUG, "%s; %s: Spurious ACK, " + "segment rejected " + "(syncookies disabled)\n", + s, __func__); + goto failed; + } + if (sch->sch_last_overflow < + time_uptime - SYNCOOKIE_LIFETIME) { + /* + * Since the bucket did not overflow recently, + * don't even check for a valid syncookie. + */ + SCH_UNLOCK(sch); + TCPSTAT_INC(tcps_sc_spurcookie); + if ((s = tcp_log_addrs(inc, th, NULL, NULL))) + log(LOG_DEBUG, "%s; %s: Spurious ACK, " + "segment rejected " + "(no syncache entry)\n", + s, __func__); + goto failed; + } SCH_UNLOCK(sch); - TCPSTAT_INC(tcps_sc_spurcookie); - if ((s = tcp_log_addrs(inc, th, NULL, NULL))) - log(LOG_DEBUG, "%s; %s: Spurious ACK, " - "segment rejected (no syncache entry)\n", - s, __func__); - goto failed; } - if (locked) - SCH_UNLOCK(sch); bzero(&scs, sizeof(scs)); + /* + * Now check, if the syncookie is valid. If it is, create an on + * stack syncache entry. + */ if (syncookie_expand(inc, sch, &scs, th, to, *lsop, port)) { sc = &scs; TCPSTAT_INC(tcps_sc_recvcookie); @@ -1291,7 +1298,7 @@ syncache_expand(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th, if (__predict_false(*lsop == NULL)) { TCPSTAT_INC(tcps_sc_aborted); TCPSTATES_DEC(TCPS_SYN_RECEIVED); - } else + } else if (sc != &scs) TCPSTAT_INC(tcps_sc_completed); if (sc != &scs) @@ -1668,7 +1675,7 @@ syncache_add(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th, sc->sc_tsoff = tcp_new_ts_offset(inc); } if ((to->to_flags & TOF_SCALE) && (V_tcp_do_rfc1323 != 3)) { - int wscale = 0; + u_int wscale = 0; /* * Pick the smallest possible scaling factor that @@ -1718,13 +1725,13 @@ syncache_add(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th, if (V_tcp_do_ecn && (tp->t_flags2 & TF2_CANNOT_DO_ECN) == 0) sc->sc_flags |= tcp_ecn_syncache_add(tcp_get_flags(th), iptos); - if (V_tcp_syncookies) + if (V_tcp_syncookies || V_tcp_syncookiesonly) sc->sc_iss = syncookie_generate(sch, sc); else sc->sc_iss = arc4random(); #ifdef INET6 if (autoflowlabel) { - if (V_tcp_syncookies) + if (V_tcp_syncookies || V_tcp_syncookiesonly) sc->sc_flowlabel = sc->sc_iss; else sc->sc_flowlabel = ip6_randomflowlabel(); @@ -2264,7 +2271,7 @@ syncookie_expand(struct in_conninfo *inc, const struct syncache_head *sch, uint32_t hash; uint8_t *secbits; tcp_seq ack, seq; - int wnd, wscale = 0; + int wnd; union syncookie cookie; /* @@ -2315,12 +2322,14 @@ syncookie_expand(struct in_conninfo *inc, const struct syncache_head *sch, sc->sc_peer_mss = tcp_sc_msstab[cookie.flags.mss_idx]; - /* We can simply recompute receive window scale we sent earlier. */ - while (wscale < TCP_MAX_WINSHIFT && (TCP_MAXWIN << wscale) < sb_max) - wscale++; - /* Only use wscale if it was enabled in the orignal SYN. */ if (cookie.flags.wscale_idx > 0) { + u_int wscale = 0; + + /* Recompute the receive window scale that was sent earlier. */ + while (wscale < TCP_MAX_WINSHIFT && + (TCP_MAXWIN << wscale) < sb_max) + wscale++; sc->sc_requested_r_scale = wscale; sc->sc_requested_s_scale = tcp_sc_wstab[cookie.flags.wscale_idx]; sc->sc_flags |= SCF_WINSCALE; diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c index 3e6519118a40..cea8a916679b 100644 --- a/sys/netinet/udp_usrreq.c +++ b/sys/netinet/udp_usrreq.c @@ -223,16 +223,18 @@ VNET_SYSUNINIT(udp, SI_SUB_PROTO_DOMAIN, SI_ORDER_FOURTH, udp_destroy, NULL); * udp_append() will convert to a sockaddr_in6 before passing the address * into the socket code. * - * In the normal case udp_append() will return 0, indicating that you - * must unlock the inp. However if a tunneling protocol is in place we increment - * the inpcb refcnt and unlock the inp, on return from the tunneling protocol we - * then decrement the reference count. If the inp_rele returns 1, indicating the - * inp is gone, we return that to the caller to tell them *not* to unlock - * the inp. In the case of multi-cast this will cause the distribution - * to stop (though most tunneling protocols known currently do *not* use - * multicast). + * In the normal case udp_append() will return 'false', indicating that you + * must unlock the inpcb. However if a tunneling protocol is in place we + * increment the inpcb refcnt and unlock the inpcb, on return from the tunneling + * protocol we then decrement the reference count. If in_pcbrele_rlocked() + * returns 'true', indicating the inpcb is gone, we return that to the caller + * to tell them *not* to unlock the inpcb. In the case of multicast this will + * cause the distribution to stop (though most tunneling protocols known + * currently do *not* use multicast). + * + * The mbuf is always consumed. */ -static int +static bool udp_append(struct inpcb *inp, struct ip *ip, struct mbuf *n, int off, struct sockaddr_in *udp_in) { @@ -255,15 +257,16 @@ udp_append(struct inpcb *inp, struct ip *ip, struct mbuf *n, int off, in_pcbref(inp); INP_RUNLOCK(inp); - filtered = (*up->u_tun_func)(n, off, inp, (struct sockaddr *)&udp_in[0], - up->u_tun_ctx); + filtered = (*up->u_tun_func)(n, off, inp, + (struct sockaddr *)&udp_in[0], up->u_tun_ctx); INP_RLOCK(inp); - if (in_pcbrele_rlocked(inp)) - return (1); - if (filtered) { - INP_RUNLOCK(inp); - return (1); + if (in_pcbrele_rlocked(inp)) { + if (!filtered) + m_freem(n); + return (true); } + if (filtered) + return (false); } off += sizeof(struct udphdr); @@ -273,18 +276,18 @@ udp_append(struct inpcb *inp, struct ip *ip, struct mbuf *n, int off, if (IPSEC_ENABLED(ipv4) && IPSEC_CHECK_POLICY(ipv4, n, inp) != 0) { m_freem(n); - return (0); + return (false); } if (up->u_flags & UF_ESPINUDP) {/* IPSec UDP encaps. */ if (IPSEC_ENABLED(ipv4) && UDPENCAP_INPUT(ipv4, n, off, AF_INET) != 0) - return (0); /* Consumed. */ + return (false); } #endif /* IPSEC */ #ifdef MAC if (mac_inpcb_check_deliver(inp, n) != 0) { m_freem(n); - return (0); + return (false); } #endif /* MAC */ if (inp->inp_flags & INP_CONTROLOPTS || @@ -330,7 +333,7 @@ udp_append(struct inpcb *inp, struct ip *ip, struct mbuf *n, int off, UDPSTAT_INC(udps_fullsock); } else sorwakeup_locked(so); - return (0); + return (false); } static bool @@ -699,7 +702,7 @@ udp_input(struct mbuf **mp, int *offp, int proto) UDPLITE_PROBE(receive, NULL, inp, ip, inp, uh); else UDP_PROBE(receive, NULL, inp, ip, inp, uh); - if (udp_append(inp, ip, m, iphlen, udp_in) == 0) + if (!udp_append(inp, ip, m, iphlen, udp_in)) INP_RUNLOCK(inp); return (IPPROTO_DONE); diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c index ce0655408a28..a9e6c4eaa51b 100644 --- a/sys/netinet6/in6.c +++ b/sys/netinet6/in6.c @@ -1236,8 +1236,8 @@ in6_addifaddr(struct ifnet *ifp, struct in6_aliasreq *ifra, struct in6_ifaddr *i int error; /* Check if this interface is a bridge member */ - if (ifp->if_bridge && bridge_member_ifaddrs_p && - !bridge_member_ifaddrs_p()) { + if (ifp->if_bridge != NULL && ifp->if_type != IFT_GIF && + bridge_member_ifaddrs_p != NULL && !bridge_member_ifaddrs_p()) { error = EINVAL; goto out; } diff --git a/tests/sys/net/if_bridge_test.sh b/tests/sys/net/if_bridge_test.sh index 0c19903714b1..b3405fd978c8 100755 --- a/tests/sys/net/if_bridge_test.sh +++ b/tests/sys/net/if_bridge_test.sh @@ -586,6 +586,25 @@ gif_body() jexec one ping -c 1 -s 1200 198.51.100.2 atf_check -s exit:0 -o ignore \ jexec one ping -c 1 -s 2000 198.51.100.2 + + # Assigning IP addresses on the gif tunneling interfaces + jexec one sysctl net.link.bridge.member_ifaddrs=1 + atf_check -s exit:0 -o ignore \ + jexec one ifconfig ${gif_one} 192.168.0.224/24 192.168.169.254 + atf_check -s exit:0 -o ignore \ + jexec one ifconfig ${gif_one} inet6 no_dad 2001:db8::1/64 + jexec one ifconfig ${bridge_one} deletem ${gif_one} + atf_check -s exit:0 -o ignore \ + jexec one ifconfig ${bridge_one} addm ${gif_one} + + jexec two sysctl net.link.bridge.member_ifaddrs=0 + atf_check -s exit:0 -o ignore \ + jexec two ifconfig ${gif_two} 192.168.169.254/24 192.168.0.224 + atf_check -s exit:0 -o ignore \ + jexec two ifconfig ${gif_two} inet6 no_dad 2001:db8::2/64 + jexec two ifconfig ${bridge_two} deletem ${gif_two} + atf_check -s exit:0 -o ignore \ + jexec two ifconfig ${bridge_two} addm ${gif_two} } gif_cleanup() diff --git a/usr.bin/netstat/inet.c b/usr.bin/netstat/inet.c index 7014f02032c2..5f36b1599cad 100644 --- a/usr.bin/netstat/inet.c +++ b/usr.bin/netstat/inet.c @@ -767,15 +767,20 @@ tcp_stats(u_long off, const char *name, int af1 __unused, int proto __unused) p1a(tcps_sc_badack, "\t\t{:bad-ack/%ju} {N:/badack}\n"); p1a(tcps_sc_unreach, "\t\t{:unreachable/%ju} {N:/unreach}\n"); p(tcps_sc_zonefail, "\t\t{:zone-failures/%ju} {N:/zone failure%s}\n"); + + xo_close_container("syncache"); + + xo_open_container("syncookies"); + p(tcps_sc_sendcookie, "\t{:sent-cookies/%ju} {N:/cookie%s sent}\n"); - p(tcps_sc_recvcookie, "\t{:received-cookies/%ju} " + p(tcps_sc_recvcookie, "\t\t{:received-cookies/%ju} " "{N:/cookie%s received}\n"); - p(tcps_sc_spurcookie, "\t{:spurious-cookies/%ju} " + p(tcps_sc_spurcookie, "\t\t{:spurious-cookies/%ju} " "{N:/spurious cookie%s rejected}\n"); - p(tcps_sc_failcookie, "\t{:failed-cookies/%ju} " + p(tcps_sc_failcookie, "\t\t{:failed-cookies/%ju} " "{N:/failed cookie%s rejected}\n"); - xo_close_container("syncache"); + xo_close_container("syncookies"); xo_open_container("hostcache"); diff --git a/usr.bin/patch/pch.c b/usr.bin/patch/pch.c index 9bc4599026ae..71f73125a8cb 100644 --- a/usr.bin/patch/pch.c +++ b/usr.bin/patch/pch.c @@ -1054,7 +1054,7 @@ hunk_done: p_end = fillnew; malformed(); } - if (ch != ' ' && context >= 0) { + if (ch != ' ' && context > 0) { if (context < p_context) p_context = context; context = -1000; diff --git a/usr.bin/patch/tests/unified_patch_test.sh b/usr.bin/patch/tests/unified_patch_test.sh index a4b46ef34221..a91332908773 100755 --- a/usr.bin/patch/tests/unified_patch_test.sh +++ b/usr.bin/patch/tests/unified_patch_test.sh @@ -25,26 +25,6 @@ # SUCH DAMAGE. # -atf_test_case badfuzz -badfuzz_head() -{ - atf_set "descr" "Test for patch(1) erroneously fuzzing away action lines" -} -badfuzz_body() -{ - # PR 250511 demonstrates a scenario where patch(1) will happily apply a - # patch into the wrong location if we have some lines that are still - # similar in the trailing context. In the following example, it would - # actually replace the underscore before the second series of B\nC\nO - # with "Z", when the patch should have been rejected instead. - printf "A\nB\nC\nO\n_\nB\nC\nO\n" > file.orig - printf "Z\nB\nC\nO\n_\nB\nC\nO\n" > file - printf "OK\nDIFF1\nDIFF2\n\n_\nB\nC\nO\n" > file.newer - - atf_check -s not-exit:0 -o save:file.patch diff -u3 file.orig file - atf_check -s not-exit:0 -o not-empty patch file.newer file.patch -} - atf_test_case basic basic_body() { @@ -198,7 +178,6 @@ EOF atf_init_test_cases() { - atf_add_test_case badfuzz atf_add_test_case basic atf_add_test_case limited_ctx atf_add_test_case file_creation diff --git a/usr.sbin/fwget/pci/pci b/usr.sbin/fwget/pci/pci index fbdfa0001c5c..de8b7c8bb2b3 100644 --- a/usr.sbin/fwget/pci/pci +++ b/usr.sbin/fwget/pci/pci @@ -27,7 +27,7 @@ pci_get_class() { - local hexclass=$(echo $1 | sed 's/.*class=\(0x[0-9a-z]\{2\}\).*/\1/') + local hexclass=$(echo $1 | sed 's/.*class=\(0x[0-9a-f]\{2\}\).*/\1/') case "${hexclass}" in 0x00) echo "old" ;; # built before class codes were finalized 0x02) echo "network" ;; @@ -38,7 +38,7 @@ pci_get_class() pci_get_vendor() { - local hexvendor=$(echo $1 | sed 's/.*\ vendor=\(0x[0-9a-z]*\).*/\1/') + local hexvendor=$(echo $1 | sed 's/.*\ vendor=\(0x[0-9a-f]*\).*/\1/') case "${hexvendor}" in 0x1002) echo "amd" ;; @@ -52,7 +52,7 @@ pci_get_vendor() pci_get_device() { - local hexdevice=$(echo $1 | sed 's/.*\ device=\(0x[0-9a-z]*\).*/\1/') + local hexdevice=$(echo $1 | sed 's/.*\ device=\(0x[0-9a-f]*\).*/\1/') echo ${hexdevice} } diff --git a/usr.sbin/fwget/pci/pci_video_amd b/usr.sbin/fwget/pci/pci_video_amd index 5017789b9f28..7e50454d3944 100644 --- a/usr.sbin/fwget/pci/pci_video_amd +++ b/usr.sbin/fwget/pci/pci_video_amd @@ -48,7 +48,7 @@ pci_video_amd() 0x13*) addpkg "gpu-firmware-amd-kmod-kaveri" ;; - 0x664*|0x664*) + 0x664*|0x665*) addpkg "gpu-firmware-amd-kmod-bonaire" ;; 0x67a*|0x67b*) @@ -72,7 +72,7 @@ pci_video_amd() 0x987*) addpkg "gpu-firmware-amd-kmod-carrizo" ;; - 0x98e4*) + 0x98e4) addpkg "gpu-firmware-amd-kmod-stoney" ;; 0x67e*|0x67ff) @@ -111,7 +111,10 @@ pci_video_amd() 0x734*) addpkg "gpu-firmware-amd-kmod-navi14" ;; - 0x15e7|0x1636|0x1638|0x164c) + 0x15e7|0x1638) + addpkg "gpu-firmware-amd-kmod-renoir gpu-firmware-amd-kmod-green-sardine" + ;; + 0x1636|0x164c) addpkg "gpu-firmware-amd-kmod-renoir" ;; 0x736*) @@ -135,7 +138,7 @@ pci_video_amd() 0x740*|0x741*) addpkg "gpu-firmware-amd-kmod-aldebaran" ;; - 0x13fe) + 0x13fe|0x143f) addpkg "gpu-firmware-amd-kmod-cyan-skillfish2" ;; 0x742*|0x743*) diff --git a/usr.sbin/newsyslog/newsyslog.8 b/usr.sbin/newsyslog/newsyslog.8 index 6d4fc378e790..7429e3b8eb01 100644 --- a/usr.sbin/newsyslog/newsyslog.8 +++ b/usr.sbin/newsyslog/newsyslog.8 @@ -14,7 +14,7 @@ .\" the suitability of this software for any purpose. It is .\" provided "as is" without express or implied warranty. .\" -.Dd December 22, 2023 +.Dd September 1, 2025 .Dt NEWSYSLOG 8 .Os .Sh NAME @@ -24,7 +24,6 @@ .Nm .Op Fl CFNPnrsv .Op Fl a Ar directory -.Op Fl c Ar none Ns | Ns Ar legacy Ns | Ns Ar bzip2 Ns | Ns Ar gzip Ns | Ns Ar xz Ns | Ns Ar zstd .Op Fl d Ar directory .Op Fl f Ar config_file .Op Fl S Ar pidfile @@ -79,25 +78,6 @@ and mode three (above) assumes that this is so. The following options can be used with .Nm : .Bl -tag -width indent -.It Fl c Ar none Ns | Ns Ar legacy Ns | Ns Ar bzip2 Ns | Ns Ar gzip Ns | Ns Ar xz Ns | Ns Ar zstd -Instructs -.Nm -to use the specified compression method when a file is flagged for compression. -The default method is -.Dq legacy , -which interprets the -.Sy J, X, Y, Z -flags in the configuration file according to their historical meanings. -This default setting can be overridden by specifying -.Fl c Ar none , -which causes -.Nm -to ignore all compression flags. -Alternatively, specifying one of the compression methods: -.Sy bzip2 , gzip , xz , -or -.Sy zstd , -will apply the chosen method to all files flagged for compression. .It Fl f Ar config_file Instruct .Nm diff --git a/usr.sbin/newsyslog/newsyslog.c b/usr.sbin/newsyslog/newsyslog.c index d07f302fd24f..7ebdd7cbc0dd 100644 --- a/usr.sbin/newsyslog/newsyslog.c +++ b/usr.sbin/newsyslog/newsyslog.c @@ -701,19 +701,12 @@ parse_args(int argc, char **argv) hostname_shortlen = strcspn(hostname, "."); /* Parse command line options. */ - while ((ch = getopt(argc, argv, "a:c:d:f:nrst:vCD:FNPR:S:")) != -1) + while ((ch = getopt(argc, argv, "a:d:f:nrst:vCD:FNPR:S:")) != -1) switch (ch) { case 'a': archtodir++; archdirname = optarg; break; - case 'c': - if (!parse_compression_type(optarg, &compress_type_override)) { - warnx("Unrecognized compression method '%s'.", optarg); - usage(); - } - compress_type_set = true; - break; case 'd': destdir = optarg; break; @@ -858,26 +851,10 @@ parse_doption(const char *doption) static void usage(void) { - int i; - char *alltypes = NULL, *tmp = NULL; - - for (i = 0; i < COMPRESS_TYPES; i++) { - if (i == COMPRESS_NONE) { - (void)asprintf(&tmp, "%s|legacy", compress_type[i].name); - } else { - (void)asprintf(&tmp, "%s|%s", alltypes, compress_type[i].name); - } - if (alltypes) - free(alltypes); - alltypes = tmp; - tmp = NULL; - } fprintf(stderr, - "usage: newsyslog [-CFNPnrsv] [-a directory] [-c %s]\n" - " [-d directory] [-f config_file]\n" - " [-S pidfile] [-t timefmt] [[-R tagname] file ...]\n", - alltypes); + "usage: newsyslog [-CFNPnrsv] [-a directory] [-d directory] [-f config_file]\n" + " [-S pidfile] [-t timefmt] [[-R tagname] file ...]\n"); exit(1); } diff --git a/usr.sbin/newsyslog/newsyslog.conf.5 b/usr.sbin/newsyslog/newsyslog.conf.5 index 2887ecb226aa..d94c39332597 100644 --- a/usr.sbin/newsyslog/newsyslog.conf.5 +++ b/usr.sbin/newsyslog/newsyslog.conf.5 @@ -18,7 +18,7 @@ .\" the suitability of this software for any purpose. It is .\" provided "as is" without express or implied warranty. .\" -.Dd November 11, 2024 +.Dd September 1, 2025 .Dt NEWSYSLOG.CONF 5 .Os .Sh NAME @@ -44,8 +44,7 @@ reads a configuration file, normally .Pa /etc/newsyslog.conf , to determine which logs may potentially be rotated and archived. -Each line has five mandatory fields and four optional fields, -separated with whitespace. +.Pp Blank lines or lines beginning with .Ql # are ignored. @@ -63,34 +62,73 @@ in this case preceding is removed and .Ql # is treated as an ordinary character. +.Pp +The special +.Dq Ar <compress> +and +.Dq Ar <include> +lines are defined as follows: +.Bl -tag -width indent +.It Ar <compress> Ns Ar none Ns | Ns Ar legacy Ns | Ns Ar bzip2 Ns | Ns Ar gzip Ns | Ns Ar xz Ns | Ns Ar zstd +This special option sets the global compress method, +it should be placed before all log file entries in +.Nm +configuration file. +The global compress method applies to all log files flagged as +compressible +.Dq Sy J , +.Dq Sy X , +.Dq Sy Y , +.Dq Sy Z +.Ar flags +below. +.Pp +The following compression methods are available: +.Bl -tag -width indent +.It Cm none +No compression is performed, even when a log file is marked as +compressible. This is useful for filesystems that have native +compression support. +.It Cm legacy +Interprets the +.Sy J, X, Y, Z +flags in the configuration file according to their historical meanings. +This is the default method. +.It Cm bzip2 +Use +.Xr bzip2 1 +for all compressible log files. +.It Cm gzip +Use +.Xr gzip 1 +for all compressible log files. +.It Cm xz +Use +.Xr xz 1 +for all compressible log files. +.It Cm zstd +Use +.Xr zstd 1 +for all compressible log files. +.El +.It Ar <include> +The special <include> entry is used to include other configuration +files and supports globbing. +.El +.Pp +Each other line has five mandatory fields and four optional fields, +separated with whitespace. The fields of the configuration file are as follows: .Bl -tag -width indent .It Ar logfile_name Name of the system log file to be archived, -or one of the special strings -.Dq Li <compress> , -.Dq Li <default> , -or -.Dq Li <include> . -The <compress> entry, -which should be placed at the beginning of the -.Nm -configuration file, -sets the global compress method. -This method is applied when a log file is flagged as -compressible, -which has the same effect of passing a compress method to the -.Fl c -option on the -.Xr newsyslog 8 -command line. +or the special string +.Dq Ar <default> . The special <default> entry will only be used if a log file name is given as a command line argument to .Xr newsyslog 8 , and if that log file name is not matched by any other line in the configuration file. -The include entry is used to include other configuration -files and supports globbing. .It Ar owner : Ns Ar group This optional field specifies the owner and group for the archive file. The @@ -432,7 +470,7 @@ can be the signal number, e.g., 30 for .El .Sh EXAMPLES The following is an example of the -.Dq Aq Li include +.Dq <include> entry: .Dl "<include> /etc/newsyslog-local.conf" .Sh SEE ALSO diff --git a/usr.sbin/ngctl/Makefile b/usr.sbin/ngctl/Makefile index 72a5ccaa96d7..997841272376 100644 --- a/usr.sbin/ngctl/Makefile +++ b/usr.sbin/ngctl/Makefile @@ -13,4 +13,9 @@ LIBADD= netgraph CFLAGS+= -DEDITLINE LIBADD+= edit pthread +.if ${MK_JAIL} != "no" +CFLAGS+= -DJAIL +LIBADD+= jail +.endif + .include <bsd.prog.mk> diff --git a/usr.sbin/ngctl/main.c b/usr.sbin/ngctl/main.c index 7c79e67d8275..b32e4f878b6e 100644 --- a/usr.sbin/ngctl/main.c +++ b/usr.sbin/ngctl/main.c @@ -55,6 +55,10 @@ #include <histedit.h> #include <pthread.h> #endif +#ifdef JAIL +#include <sys/jail.h> +#include <jail.h> +#endif #include <netgraph.h> @@ -137,16 +141,17 @@ int csock, dsock; int main(int ac, char *av[]) { - char name[NG_NODESIZ]; - int interactive = isatty(0) && isatty(1); - FILE *fp = NULL; - int ch, rtn = 0; + char name[NG_NODESIZ]; + int interactive = isatty(0) && isatty(1); + FILE *fp = NULL; + const char *jail_name = NULL; + int ch, rtn = 0; /* Set default node name */ snprintf(name, sizeof(name), "ngctl%d", getpid()); /* Parse command line */ - while ((ch = getopt(ac, av, "df:n:")) != -1) { + while ((ch = getopt(ac, av, "df:j:n:")) != -1) { switch (ch) { case 'd': NgSetDebug(NgSetDebug(-1) + 1); @@ -157,6 +162,13 @@ main(int ac, char *av[]) else if ((fp = fopen(optarg, "r")) == NULL) err(EX_NOINPUT, "%s", optarg); break; + case 'j': +#ifdef JAIL + jail_name = optarg; +#else + errx(EX_UNAVAILABLE, "not built with jail support"); +#endif + break; case 'n': snprintf(name, sizeof(name), "%s", optarg); break; @@ -169,6 +181,22 @@ main(int ac, char *av[]) ac -= optind; av += optind; + if (jail_name != NULL) { + int jid; + + if (jail_name[0] == '\0') + Usage("invalid jail name"); + + jid = jail_getid(jail_name); + + if (jid == -1) + errx((errno == EPERM) ? EX_NOPERM : EX_NOHOST, + "%s", jail_errmsg); + if (jail_attach(jid) != 0) + errx((errno == EPERM) ? EX_NOPERM : EX_OSERR, + "cannot attach to jail"); + } + /* Create a new socket node */ if (NgMkSockNode(name, &csock, &dsock) < 0) err(EX_OSERR, "can't create node"); @@ -657,6 +685,7 @@ Usage(const char *msg) if (msg) warnx("%s", msg); fprintf(stderr, - "usage: ngctl [-d] [-f file] [-n name] [command ...]\n"); + "usage: ngctl [-j jail] [-d] [-f filename] [-n nodename] " + "[command [argument ...]]\n"); exit(EX_USAGE); } diff --git a/usr.sbin/ngctl/ngctl.8 b/usr.sbin/ngctl/ngctl.8 index 2225c836674a..63b8f58ed3df 100644 --- a/usr.sbin/ngctl/ngctl.8 +++ b/usr.sbin/ngctl/ngctl.8 @@ -31,7 +31,7 @@ .\" OF SUCH DAMAGE. .\" $Whistle: ngctl.8,v 1.6 1999/01/20 03:19:44 archie Exp $ .\" -.Dd January 19, 1999 +.Dd August 29, 2025 .Dt NGCTL 8 .Os .Sh NAME @@ -39,9 +39,11 @@ .Nd netgraph control utility .Sh SYNOPSIS .Nm +.Op Fl j Ar jail .Op Fl d .Op Fl f Ar filename .Op Fl n Ar nodename +.Op Ar command Op Ns Ar argument ... .Op Ar command ... .Sh DESCRIPTION The @@ -73,12 +75,31 @@ form if the originating node supports conversion. .Pp The options are as follows: .Bl -tag -width indent -.It Fl f Ar nodeinfo +.It Fl f Ar filename Read commands from the named file. A single dash represents the standard input. Blank lines and lines starting with a .Dq # are ignored. +Note that when the +.Fl j Ar jail +option is specified, the file will be opened before attaching to the jail and +then be processed inside the jail. +.It Fl j Ar jail +Perform the actions inside the +.Ar jail . +.Pp +.Nm +will first attach to the +.Ar jail +(by jail id or jail name) before performing the effects. +.Pp +This allows netgraph nodes of +.Ar jail +to be created, modified, and destroyed even if the +.Nm +binary is not available in +.Ar jail . .It Fl n Ar nodename Assign .Em nodename |