summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorneel <neel@FreeBSD.org>2012-11-11 03:26:14 +0000
committerneel <neel@FreeBSD.org>2012-11-11 03:26:14 +0000
commitbc4be3dff1bc1b0cdc3ea30df0fd3e83998cf9eb (patch)
treeb6b271fb331d43e30e10d824f2042de2c063f2eb /lib
parent263c4acf84c3be71025f3484c0378a83cd668e15 (diff)
parentde6ea8b20e870490db809a8d8a965bd784981d81 (diff)
downloadFreeBSD-src-bc4be3dff1bc1b0cdc3ea30df0fd3e83998cf9eb.zip
FreeBSD-src-bc4be3dff1bc1b0cdc3ea30df0fd3e83998cf9eb.tar.gz
IFC @ r242684
Diffstat (limited to 'lib')
-rw-r--r--lib/Makefile21
-rw-r--r--lib/atf/Makefile36
-rw-r--r--lib/atf/Makefile.inc54
-rw-r--r--lib/atf/libatf-c++/Makefile76
-rw-r--r--lib/atf/libatf-c/Makefile76
-rw-r--r--lib/clang/Makefile1
-rw-r--r--lib/clang/clang.build.mk42
-rw-r--r--lib/clang/clang.lib.mk2
-rw-r--r--lib/clang/include/Makefile12
-rw-r--r--lib/clang/include/MipsGenDisassemblerTables.inc2
-rw-r--r--lib/clang/include/MipsGenEDInfo.inc2
-rw-r--r--lib/clang/include/clang/AST/CommentNodes.inc2
-rw-r--r--lib/clang/include/clang/Basic/DiagnosticCommentKinds.inc2
-rw-r--r--lib/clang/include/clang/Basic/Version.inc8
-rw-r--r--lib/clang/include/clang/Driver/CC1Options.inc2
-rw-r--r--lib/clang/include/llvm/Config/AsmParsers.def1
-rw-r--r--lib/clang/include/llvm/Config/Disassemblers.def1
-rw-r--r--lib/clang/include/llvm/Config/config.h14
-rw-r--r--lib/clang/include/llvm/Config/llvm-config.h5
-rw-r--r--lib/clang/libclanganalysis/Makefile1
-rw-r--r--lib/clang/libclangarcmigrate/Makefile1
-rw-r--r--lib/clang/libclangast/Makefile10
-rw-r--r--lib/clang/libclangbasic/Makefile3
-rw-r--r--lib/clang/libclangcodegen/Makefile1
-rw-r--r--lib/clang/libclangdriver/Makefile2
-rw-r--r--lib/clang/libclangedit/Makefile1
-rw-r--r--lib/clang/libclangfrontend/Makefile2
-rw-r--r--lib/clang/libclangfrontendtool/Makefile6
-rw-r--r--lib/clang/libclangparse/Makefile1
-rw-r--r--lib/clang/libclangrewrite/Makefile2
-rw-r--r--lib/clang/libclangsema/Makefile2
-rw-r--r--lib/clang/libclangserialization/Makefile1
-rw-r--r--lib/clang/libclangstaticanalyzercheckers/Makefile5
-rw-r--r--lib/clang/libclangstaticanalyzercore/Makefile4
-rw-r--r--lib/clang/libclangstaticanalyzerfrontend/Makefile1
-rw-r--r--lib/clang/libllvmanalysis/Makefile2
-rw-r--r--lib/clang/libllvmcodegen/Makefile5
-rw-r--r--lib/clang/libllvmcore/Makefile3
-rw-r--r--lib/clang/libllvminstrumentation/Makefile1
-rw-r--r--lib/clang/libllvmmc/Makefile7
-rw-r--r--lib/clang/libllvmmipscodegen/Makefile11
-rw-r--r--lib/clang/libllvmmipsdisassembler/Makefile15
-rw-r--r--lib/clang/libllvmmipsinstprinter/Makefile3
-rw-r--r--lib/clang/libllvmpowerpccodegen/Makefile1
-rw-r--r--lib/clang/libllvmtablegen/Makefile1
-rw-r--r--lib/libarchive/Makefile5
-rw-r--r--lib/libarchive/config_freebsd.h4
-rw-r--r--lib/libarchive/test/Makefile8
-rw-r--r--lib/libc++/Makefile21
-rw-r--r--lib/libc/amd64/SYS.h26
-rw-r--r--lib/libc/amd64/Symbol.map1
-rw-r--r--lib/libc/amd64/gen/rfork_thread.S5
-rw-r--r--lib/libc/amd64/sys/brk.S5
-rw-r--r--lib/libc/amd64/sys/exect.S5
-rw-r--r--lib/libc/amd64/sys/getcontext.S9
-rw-r--r--lib/libc/amd64/sys/pipe.S9
-rw-r--r--lib/libc/amd64/sys/ptrace.S9
-rw-r--r--lib/libc/amd64/sys/reboot.S9
-rw-r--r--lib/libc/amd64/sys/sbrk.S5
-rw-r--r--lib/libc/amd64/sys/setlogin.S9
-rw-r--r--lib/libc/amd64/sys/vfork.S5
-rw-r--r--lib/libc/arm/gen/__aeabi_read_tp.S6
-rw-r--r--lib/libc/arm/gen/_set_tp.c4
-rw-r--r--lib/libc/compat-43/killpg.213
-rw-r--r--lib/libc/gen/Makefile.inc11
-rw-r--r--lib/libc/gen/Symbol.map5
-rw-r--r--lib/libc/gen/arc4random.c2
-rw-r--r--lib/libc/gen/auxv.c (renamed from lib/libc/gen/aux.c)0
-rw-r--r--lib/libc/gen/clock_getcpuclockid.395
-rw-r--r--lib/libc/gen/clock_getcpuclockid.c41
-rw-r--r--lib/libc/gen/fstab.c60
-rw-r--r--lib/libc/gen/fts-compat.c12
-rw-r--r--lib/libc/gen/fts.c15
-rw-r--r--lib/libc/gen/ftw.c3
-rw-r--r--lib/libc/gen/getcap.c2
-rw-r--r--lib/libc/gen/getcwd.c2
-rw-r--r--lib/libc/gen/nftw.c16
-rw-r--r--lib/libc/gen/nlist.c2
-rw-r--r--lib/libc/gen/opendir.c3
-rw-r--r--lib/libc/gen/pututxline.c6
-rw-r--r--lib/libc/gen/pwcache.393
-rw-r--r--lib/libc/gen/pwcache.c113
-rw-r--r--lib/libc/gen/rand48.314
-rw-r--r--lib/libc/gen/readpassphrase.c2
-rw-r--r--lib/libc/gen/sem_new.c2
-rw-r--r--lib/libc/gen/sysconf.c4
-rw-r--r--lib/libc/gen/sysctl.c7
-rw-r--r--lib/libc/gen/syslog.c3
-rw-r--r--lib/libc/i386/SYS.h12
-rw-r--r--lib/libc/i386/Symbol.map1
-rw-r--r--lib/libc/i386/gen/rfork_thread.S3
-rw-r--r--lib/libc/i386/sys/Ovfork.S3
-rw-r--r--lib/libc/i386/sys/brk.S9
-rw-r--r--lib/libc/i386/sys/cerror.S5
-rw-r--r--lib/libc/i386/sys/exect.S3
-rw-r--r--lib/libc/i386/sys/getcontext.S5
-rw-r--r--lib/libc/i386/sys/ptrace.S5
-rw-r--r--lib/libc/i386/sys/sbrk.S9
-rw-r--r--lib/libc/i386/sys/syscall.S5
-rw-r--r--lib/libc/locale/Makefile.inc20
-rw-r--r--lib/libc/locale/isgraph.320
-rw-r--r--lib/libc/locale/islower.319
-rw-r--r--lib/libc/locale/ispunct.320
-rw-r--r--lib/libc/locale/isspace.320
-rw-r--r--lib/libc/locale/iswalnum_l.3168
-rw-r--r--lib/libc/locale/ldpart.c2
-rw-r--r--lib/libc/locale/nl_langinfo.316
-rw-r--r--lib/libc/net/getaddrinfo.c27
-rw-r--r--lib/libc/net/ip6opt.c2
-rw-r--r--lib/libc/net/sctp_sys_calls.c4
-rw-r--r--lib/libc/nls/msgcat.c2
-rw-r--r--lib/libc/rpc/auth_des.c2
-rw-r--r--lib/libc/rpc/auth_unix.c11
-rw-r--r--lib/libc/rpc/authunix_prot.c14
-rw-r--r--lib/libc/rpc/clnt_vc.c4
-rw-r--r--lib/libc/rpc/getnetpath.c3
-rw-r--r--lib/libc/rpc/rpc_generic.c6
-rw-r--r--lib/libc/rpc/rpc_soc.32
-rw-r--r--lib/libc/rpc/svc_auth_des.c2
-rw-r--r--lib/libc/rpc/svc_auth_unix.c2
-rw-r--r--lib/libc/stdio/fopen.36
-rw-r--r--lib/libc/stdio/scanf_l.32
-rw-r--r--lib/libc/stdlib/at_quick_exit.33
-rw-r--r--lib/libc/stdlib/getenv.c10
-rw-r--r--lib/libc/stdlib/malloc.c6256
-rw-r--r--lib/libc/stdlib/ptsname.33
-rw-r--r--lib/libc/stdlib/ptsname.c4
-rw-r--r--lib/libc/stdlib/quick_exit.33
-rw-r--r--lib/libc/stdlib/rand.315
-rw-r--r--lib/libc/stdlib/rand.c5
-rw-r--r--lib/libc/stdlib/random.320
-rw-r--r--lib/libc/stdlib/random.c34
-rw-r--r--lib/libc/stdlib/realpath.c2
-rw-r--r--lib/libc/string/ffs.39
-rw-r--r--lib/libc/string/strerror.36
-rw-r--r--lib/libc/string/strsignal.c42
-rw-r--r--lib/libc/sys/Symbol.map3
-rw-r--r--lib/libc/sys/dup.21
-rw-r--r--lib/libc/sys/fcntl.233
-rw-r--r--lib/libc/sys/fcntl.c2
-rw-r--r--lib/libc/sys/kill.223
-rw-r--r--lib/libc/sys/listen.222
-rw-r--r--lib/libc/sys/recv.224
-rw-r--r--lib/libc/sys/sigaction.29
-rw-r--r--lib/libc/sys/sigwait.25
-rw-r--r--lib/libc/sys/sigwaitinfo.25
-rw-r--r--lib/libc/sys/wait.22
-rw-r--r--lib/libc/yp/yplib.c2
-rw-r--r--lib/libdwarf/dwarf.h1
-rw-r--r--lib/libdwarf/dwarf_attrval.c1
-rw-r--r--lib/libdwarf/dwarf_dump.c3
-rw-r--r--lib/libdwarf/dwarf_errmsg.c2
-rw-r--r--lib/libdwarf/dwarf_init.c6
-rw-r--r--lib/libedit/editline.35
-rw-r--r--lib/libedit/el.c24
-rw-r--r--lib/libedit/el.h1
-rw-r--r--lib/libedit/histedit.h7
-rw-r--r--lib/libedit/makelist4
-rw-r--r--lib/libedit/read.c60
-rw-r--r--lib/libedit/sig.c6
-rw-r--r--lib/libedit/sig.h3
-rw-r--r--lib/libedit/term.c2
-rw-r--r--lib/libedit/tokenizer.c6
-rw-r--r--lib/libelf/Makefile6
-rw-r--r--lib/libelf/elf_errmsg.c2
-rw-r--r--lib/libfetch/Makefile4
-rw-r--r--lib/libfetch/common.h2
-rw-r--r--lib/libfetch/file.c10
-rw-r--r--lib/libfetch/http.c28
-rw-r--r--lib/libfetch/http.errors1
-rw-r--r--lib/libgeom/geom_xml2tree.c41
-rw-r--r--lib/libjail/jail.c30
-rw-r--r--lib/libkvm/kvm_i386.c1
-rw-r--r--lib/libkvm/kvm_proc.c12
-rw-r--r--lib/libmagic/Makefile6
-rw-r--r--lib/libmagic/config.h2
-rw-r--r--lib/libmandoc/Makefile20
-rw-r--r--lib/libmemstat/memstat_uma.c2
-rw-r--r--lib/libpam/modules/pam_krb5/pam_krb5.c21
-rw-r--r--lib/libpam/modules/pam_lastlog/pam_lastlog.82
-rw-r--r--lib/libpam/modules/pam_radius/pam_radius.c1
-rw-r--r--lib/libpam/modules/pam_unix/pam_unix.c4
-rw-r--r--lib/libpcap/config.h8
-rw-r--r--lib/libpmc/Makefile4
-rw-r--r--lib/libpmc/libpmc.c100
-rw-r--r--lib/libpmc/pmc.ivybridge.3880
-rw-r--r--lib/libpmc/pmc.sandybridge.3116
-rw-r--r--lib/libpmc/pmc.sandybridgeuc.33
-rw-r--r--lib/libpmc/pmc.sandybridgexeon.31023
-rw-r--r--lib/libproc/Makefile10
-rw-r--r--lib/libproc/proc_sym.c77
-rw-r--r--lib/libproc/test/t1-bkpt/t1-bkpt.c6
-rw-r--r--lib/libproc/test/t3-name2sym/t3-name2sym.c1
-rw-r--r--lib/libprocstat/Makefile7
-rw-r--r--lib/libprocstat/common_kvm.h3
-rw-r--r--lib/libprocstat/libprocstat.c12
-rw-r--r--lib/libprocstat/libprocstat.h2
-rw-r--r--lib/librpcsec_gss/svc_rpcsec_gss.c4
-rw-r--r--lib/libstand/nandfs.c15
-rw-r--r--lib/libstand/nfs.c136
-rw-r--r--lib/libstdbuf/Makefile2
-rw-r--r--lib/libthr/arch/arm/include/pthread_md.h14
-rw-r--r--lib/libthr/thread/thr_cond.c16
-rw-r--r--lib/libthr/thread/thr_fork.c3
-rw-r--r--lib/libthr/thread/thr_getcpuclockid.c4
-rw-r--r--lib/libthr/thread/thr_getschedparam.c31
-rw-r--r--lib/libthr/thread/thr_info.c6
-rw-r--r--lib/libthr/thread/thr_init.c7
-rw-r--r--lib/libthr/thread/thr_kern.c7
-rw-r--r--lib/libthr/thread/thr_mutex.c16
-rw-r--r--lib/libthr/thread/thr_private.h14
-rw-r--r--lib/libthr/thread/thr_resume_np.c7
-rw-r--r--lib/libthr/thread/thr_setprio.c44
-rw-r--r--lib/libthr/thread/thr_setschedparam.c51
-rw-r--r--lib/libthr/thread/thr_sig.c3
-rw-r--r--lib/libthr/thread/thr_suspend_np.c45
-rw-r--r--lib/libthr/thread/thr_umtx.h16
-rw-r--r--lib/libthread_db/libpthread_db.c2
-rw-r--r--lib/libthread_db/libthr_db.c2
-rw-r--r--lib/libusb/libusb20.313
-rw-r--r--lib/libusb/libusb20.c9
-rw-r--r--lib/libusb/libusb20.h1
-rw-r--r--lib/libusb/libusb20_int.h2
-rw-r--r--lib/libusb/libusb20_ugen20.c32
-rw-r--r--lib/libusbhid/descr.c2
-rw-r--r--lib/libusbhid/parse.c23
-rw-r--r--lib/libusbhid/usbhid.37
-rw-r--r--lib/libutil/Makefile15
-rw-r--r--lib/libutil/gr_util.c2
-rw-r--r--lib/libutil/humanize_number.c2
-rw-r--r--lib/libutil/pw_util.3286
-rw-r--r--lib/msun/Makefile2
-rw-r--r--lib/msun/Symbol.map1
-rw-r--r--lib/msun/i387/s_cos.S10
-rw-r--r--lib/msun/i387/s_sin.S10
-rw-r--r--lib/msun/i387/s_tan.S12
-rw-r--r--lib/msun/ld128/s_expl.c261
-rw-r--r--lib/msun/ld80/s_expl.c304
-rw-r--r--lib/msun/man/cexp.310
-rw-r--r--lib/msun/man/exp.314
-rw-r--r--lib/msun/man/ieee.367
-rw-r--r--lib/msun/src/e_exp.c4
-rw-r--r--lib/msun/src/e_rem_pio2.c6
-rw-r--r--lib/msun/src/e_rem_pio2f.c8
-rw-r--r--lib/msun/src/k_cosf.c6
-rw-r--r--lib/msun/src/k_sinf.c6
-rw-r--r--lib/msun/src/k_tanf.c6
-rw-r--r--lib/msun/src/math.h2
-rw-r--r--lib/msun/src/math_private.h66
-rw-r--r--lib/msun/src/s_cbrtl.c26
-rw-r--r--lib/msun/src/s_cosl.c9
-rw-r--r--lib/msun/src/s_sinl.c9
-rw-r--r--lib/msun/src/s_tanl.c9
253 files changed, 4868 insertions, 7496 deletions
diff --git a/lib/Makefile b/lib/Makefile
index 989ea23..d536ee0 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -85,11 +85,11 @@ SUBDIR= ${SUBDIR_ORDERED} \
libkiconv \
liblzma \
libmagic \
+ libmandoc \
libmemstat \
${_libmilter} \
${_libmp} \
${_libnandfs} \
- ${_libncp} \
${_libngatm} \
libopie \
libpam \
@@ -101,7 +101,6 @@ SUBDIR= ${SUBDIR_ORDERED} \
${_librtld_db} \
${_libsdp} \
${_libsm} \
- ${_libsmb} \
${_libsmdb} \
${_libsmutil} \
libstand \
@@ -120,6 +119,7 @@ SUBDIR= ${SUBDIR_ORDERED} \
libwrap \
liby \
libz \
+ ${_atf} \
${_bind} \
${_clang}
@@ -135,6 +135,10 @@ _csu=csu
# NB: keep these sorted by MK_* knobs
+.if ${MK_ATF} != "no"
+_atf= atf
+.endif
+
.if ${MK_ATM} != "no"
_libngatm= libngatm
.endif
@@ -190,10 +194,6 @@ _libypclnt= libypclnt
.endif
.if ${MACHINE_CPUARCH} == "i386" || ${MACHINE_CPUARCH} == "amd64"
-.if ${MK_NCP} != "no"
-_libncp= libncp
-.endif
-_libsmb= libsmb
_libvgl= libvgl
_libproc= libproc
_librtld_db= librtld_db
@@ -205,7 +205,6 @@ _libvmmapi= libvmmapi
.if ${MACHINE_CPUARCH} == "ia64"
_libefi= libefi
-_libsmb= libsmb
.endif
.if ${MACHINE_CPUARCH} == "mips"
@@ -213,14 +212,6 @@ _libproc= libproc
_librtld_db= librtld_db
.endif
-.if ${MACHINE_CPUARCH} == "powerpc"
-_libsmb= libsmb
-.endif
-
-.if ${MACHINE_CPUARCH} == "sparc64"
-_libsmb= libsmb
-.endif
-
.if ${MK_OPENSSL} != "no"
_libmp= libmp
.endif
diff --git a/lib/atf/Makefile b/lib/atf/Makefile
new file mode 100644
index 0000000..0da9aa8
--- /dev/null
+++ b/lib/atf/Makefile
@@ -0,0 +1,36 @@
+#-
+# Copyright (c) 2011 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:
+# 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 THE AUTHOR 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 AUTHOR 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.
+#
+# $FreeBSD$
+
+.include <bsd.own.mk>
+
+SUBDIR= \
+ libatf-c \
+ libatf-c++
+
+.ORDER: ${SUBDIR}
+
+.include <bsd.subdir.mk>
diff --git a/lib/atf/Makefile.inc b/lib/atf/Makefile.inc
new file mode 100644
index 0000000..937187a
--- /dev/null
+++ b/lib/atf/Makefile.inc
@@ -0,0 +1,54 @@
+#-
+# Copyright (c) 2011 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:
+# 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 THE AUTHOR 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 AUTHOR 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.
+#
+# $FreeBSD$
+
+ATF= ${.CURDIR}/../../../contrib/atf
+
+_CFLAGS:= ${CFLAGS}
+_CPPFLAGS:= ${CPPFLAGS}
+_CXXFLAGS:= ${CXXFLAGS}
+
+CFLAGS+= -DHAVE_CONFIG_H
+CFLAGS+= -DATF_ARCH='"${MACHINE}"'
+CFLAGS+= -DATF_BUILD_CC='"${CC}"'
+CFLAGS+= -DATF_BUILD_CFLAGS='"${_CFLAGS}"'
+CFLAGS+= -DATF_BUILD_CPP='"${CPP}"'
+CFLAGS+= -DATF_BUILD_CPPFLAGS='"${_CPPFLAGS}"'
+CFLAGS+= -DATF_BUILD_CXX='"${CXX}"'
+CFLAGS+= -DATF_BUILD_CXXFLAGS='"${_CXXFLAGS}"'
+CFLAGS+= -DATF_CONFDIR='"${CONFDIR}/atf"'
+CFLAGS+= -DATF_INCLUDEDIR='"${INCLUDEDIR}"'
+CFLAGS+= -DATF_LIBDIR='"${LIBDIR}"'
+CFLAGS+= -DATF_LIBEXECDIR='"${LIBEXECDIR}"'
+CFLAGS+= -DATF_MACHINE='"${MACHINE_ARCH}"'
+CFLAGS+= -DATF_M4='"/usr/bin/m4"'
+CFLAGS+= -DATF_PKGDATADIR='"${SHAREDIR}/atf"'
+CFLAGS+= -DATF_SHELL='"/bin/sh"'
+CFLAGS+= -DATF_WORKDIR='"/tmp"'
+
+WARNS?= 3
+
+# vim: syntax=make
diff --git a/lib/atf/libatf-c++/Makefile b/lib/atf/libatf-c++/Makefile
new file mode 100644
index 0000000..37d6073
--- /dev/null
+++ b/lib/atf/libatf-c++/Makefile
@@ -0,0 +1,76 @@
+#-
+# Copyright (c) 2011 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:
+# 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 THE AUTHOR 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 AUTHOR 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.
+#
+# $FreeBSD$
+
+.include <bsd.init.mk>
+
+LIB= atf-c++
+SHLIB_MAJOR= 1
+
+# libatf-c++ depends on the C version of the ATF library to build.
+DPADD= ${LIBATFC}
+LDADD= -latf-c
+
+LDFLAGS+= -L${.OBJDIR}/../libatf-c
+
+.PATH: ${ATF}
+.PATH: ${ATF}/atf-c++
+.PATH: ${ATF}/atf-c++/detail
+
+CFLAGS+= -I${ATF}
+CFLAGS+= -I${.CURDIR}/../libatf-c
+CFLAGS+= -I.
+
+CFLAGS+= -DHAVE_CONFIG_H
+
+SRCS= application.cpp \
+ build.cpp \
+ check.cpp \
+ config.cpp \
+ env.cpp \
+ exceptions.cpp \
+ expand.cpp \
+ fs.cpp \
+ parser.cpp \
+ process.cpp \
+ tests.cpp \
+ text.cpp \
+ ui.cpp
+
+INCS= build.hpp \
+ check.hpp \
+ config.hpp \
+ macros.hpp \
+ tests.hpp \
+ utils.hpp
+INCSDIR= ${INCLUDEDIR}/atf-c++
+
+INCS+= atf-c++.hpp
+INCSDIR_atf-c++.hpp= ${INCLUDEDIR}
+
+MAN= atf-c++-api.3
+
+.include <bsd.lib.mk>
diff --git a/lib/atf/libatf-c/Makefile b/lib/atf/libatf-c/Makefile
new file mode 100644
index 0000000..26fba5c
--- /dev/null
+++ b/lib/atf/libatf-c/Makefile
@@ -0,0 +1,76 @@
+#-
+# Copyright (c) 2011 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:
+# 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 THE AUTHOR 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 AUTHOR 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.
+#
+# $FreeBSD$
+
+.include <bsd.init.mk>
+
+LIB= atf-c
+SHLIB_MAJOR= 1
+
+.PATH: ${ATF}
+.PATH: ${ATF}/atf-c
+.PATH: ${ATF}/atf-c/detail
+
+CFLAGS+= -I${ATF}
+CFLAGS+= -I${.CURDIR}
+CFLAGS+= -I.
+
+SRCS= build.c \
+ check.c \
+ config.c \
+ dynstr.c \
+ env.c \
+ error.c \
+ fs.c \
+ list.c \
+ map.c \
+ process.c \
+ sanity.c \
+ text.c \
+ user.c \
+ utils.c \
+ tc.c \
+ tp.c \
+ tp_main.c
+
+INCS= build.h \
+ check.h \
+ config.h \
+ defs.h \
+ error.h \
+ error_fwd.h \
+ macros.h \
+ tc.h \
+ tp.h \
+ utils.h
+INCSDIR= ${INCLUDEDIR}/atf-c
+
+INCS+= atf-c.h
+INCSDIR_atf-c.h= ${INCLUDEDIR}
+
+MAN= atf-c-api.3
+
+.include <bsd.lib.mk>
diff --git a/lib/clang/Makefile b/lib/clang/Makefile
index 2d77383..dde515e 100644
--- a/lib/clang/Makefile
+++ b/lib/clang/Makefile
@@ -54,6 +54,7 @@ SUBDIR= libclanganalysis \
libllvmmipsasmparser \
libllvmmipscodegen \
libllvmmipsdesc \
+ libllvmmipsdisassembler \
libllvmmipsinfo \
libllvmmipsinstprinter \
libllvmpowerpccodegen \
diff --git a/lib/clang/clang.build.mk b/lib/clang/clang.build.mk
index 67868f1..40dc4ab 100644
--- a/lib/clang/clang.build.mk
+++ b/lib/clang/clang.build.mk
@@ -1,37 +1,41 @@
# $FreeBSD$
-CLANG_SRCS=${LLVM_SRCS}/tools/clang
+CLANG_SRCS= ${LLVM_SRCS}/tools/clang
-CFLAGS+=-I${LLVM_SRCS}/include -I${CLANG_SRCS}/include \
- -I${LLVM_SRCS}/${SRCDIR} ${INCDIR:C/^/-I${LLVM_SRCS}\//} -I. \
- -I${LLVM_SRCS}/../../lib/clang/include \
- -DLLVM_ON_UNIX -DLLVM_ON_FREEBSD \
- -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS #-DNDEBUG
+CFLAGS+= -I${LLVM_SRCS}/include -I${CLANG_SRCS}/include \
+ -I${LLVM_SRCS}/${SRCDIR} ${INCDIR:C/^/-I${LLVM_SRCS}\//} -I. \
+ -I${LLVM_SRCS}/../../lib/clang/include \
+ -DLLVM_ON_UNIX -DLLVM_ON_FREEBSD \
+ -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS #-DNDEBUG
# LLVM is not strict aliasing safe as of 12/31/2011
-CFLAGS+= -fno-strict-aliasing
+CFLAGS+= -fno-strict-aliasing
TARGET_ARCH?= ${MACHINE_ARCH}
-CFLAGS+=-DLLVM_DEFAULT_TARGET_TRIPLE=\"${TARGET_ARCH:C/amd64/x86_64/}-unknown-freebsd10.0\"
+BUILD_ARCH?= ${MACHINE_ARCH}
+TARGET_TRIPLE?= ${TARGET_ARCH:C/amd64/x86_64/}-unknown-freebsd10.0
+BUILD_TRIPLE?= ${BUILD_ARCH:C/amd64/x86_64/}-unknown-freebsd10.0
+CFLAGS+= -DLLVM_DEFAULT_TARGET_TRIPLE=\"${TARGET_TRIPLE}\" \
+ -DLLVM_HOSTTRIPLE=\"${BUILD_TRIPLE}\"
.ifndef LLVM_REQUIRES_EH
-CXXFLAGS+=-fno-exceptions
+CXXFLAGS+= -fno-exceptions
.else
# If the library or program requires EH, it also requires RTTI.
LLVM_REQUIRES_RTTI=
.endif
.ifndef LLVM_REQUIRES_RTTI
-CXXFLAGS+=-fno-rtti
+CXXFLAGS+= -fno-rtti
.endif
-CFLAGS+=-DDEFAULT_SYSROOT=\"${TOOLS_PREFIX}\"
+CFLAGS+= -DDEFAULT_SYSROOT=\"${TOOLS_PREFIX}\"
.PATH: ${LLVM_SRCS}/${SRCDIR}
-TBLGEN?=tblgen
-CLANG_TBLGEN?=clang-tblgen
-TBLINC+=-I ${LLVM_SRCS}/include -I ${LLVM_SRCS}/lib/Target
+TBLGEN?= tblgen
+CLANG_TBLGEN?= clang-tblgen
+TBLINC+= -I ${LLVM_SRCS}/include -I ${LLVM_SRCS}/lib/Target
Intrinsics.inc.h: ${LLVM_SRCS}/include/llvm/Intrinsics.td
${TBLGEN} -I ${LLVM_SRCS}/lib/VMCore ${TBLINC} -gen-intrinsic \
@@ -110,6 +114,10 @@ AttrTemplateInstantiate.inc.h: ${CLANG_SRCS}/include/clang/Basic/Attr.td
-gen-clang-attr-template-instantiate -o ${.TARGET} \
-I ${CLANG_SRCS}/include ${.ALLSRC}
+CommentNodes.inc.h: ${CLANG_SRCS}/include/clang/Basic/CommentNodes.td
+ ${CLANG_TBLGEN} -I ${CLANG_SRCS}/include/clang/AST ${TBLINC} \
+ -gen-clang-comment-nodes -o ${.TARGET} ${.ALLSRC}
+
DeclNodes.inc.h: ${CLANG_SRCS}/include/clang/Basic/DeclNodes.td
${CLANG_TBLGEN} -I ${CLANG_SRCS}/include/clang/AST ${TBLINC} \
-gen-clang-decl-nodes -o ${.TARGET} ${.ALLSRC}
@@ -130,7 +138,7 @@ DiagnosticIndexName.inc.h: ${CLANG_SRCS}/include/clang/Basic/Diagnostic.td
${CLANG_TBLGEN} -I ${CLANG_SRCS}/include/clang/Basic ${TBLINC} \
-gen-clang-diags-index-name -o ${.TARGET} ${.ALLSRC}
-.for hdr in AST Analysis Common Driver Frontend Lex Parse Sema Serialization
+.for hdr in AST Analysis Comment Common Driver Frontend Lex Parse Sema Serialization
Diagnostic${hdr}Kinds.inc.h: ${CLANG_SRCS}/include/clang/Basic/Diagnostic.td
${CLANG_TBLGEN} -I ${CLANG_SRCS}/include/clang/Basic ${TBLINC} \
-gen-clang-diags-defs -clang-component=${hdr} \
@@ -141,10 +149,6 @@ Options.inc.h: ${CLANG_SRCS}/include/clang/Driver/Options.td
${CLANG_TBLGEN} -I ${CLANG_SRCS}/include/clang/Driver ${TBLINC} \
-gen-opt-parser-defs -o ${.TARGET} ${.ALLSRC}
-CC1Options.inc.h: ${CLANG_SRCS}/include/clang/Driver/CC1Options.td
- ${CLANG_TBLGEN} -I ${CLANG_SRCS}/include/clang/Driver ${TBLINC} \
- -gen-opt-parser-defs -o ${.TARGET} ${.ALLSRC}
-
CC1AsOptions.inc.h: ${CLANG_SRCS}/include/clang/Driver/CC1AsOptions.td
${CLANG_TBLGEN} -I ${CLANG_SRCS}/include/clang/Driver ${TBLINC} \
-gen-opt-parser-defs -o ${.TARGET} ${.ALLSRC}
diff --git a/lib/clang/clang.lib.mk b/lib/clang/clang.lib.mk
index f7bd281..13afa85 100644
--- a/lib/clang/clang.lib.mk
+++ b/lib/clang/clang.lib.mk
@@ -1,6 +1,6 @@
# $FreeBSD$
-LLVM_SRCS=${.CURDIR}/../../../contrib/llvm
+LLVM_SRCS= ${.CURDIR}/../../../contrib/llvm
.include "clang.build.mk"
diff --git a/lib/clang/include/Makefile b/lib/clang/include/Makefile
index 05b43cf..93d91c7 100644
--- a/lib/clang/include/Makefile
+++ b/lib/clang/include/Makefile
@@ -2,9 +2,10 @@
.PATH: ${.CURDIR}/../../../contrib/llvm/tools/clang/lib/Headers
-INCSDIR=${INCLUDEDIR}/clang/3.1
+INCSDIR=${INCLUDEDIR}/clang/3.2
INCS= altivec.h \
+ ammintrin.h \
avx2intrin.h \
avxintrin.h \
bmi2intrin.h \
@@ -12,6 +13,7 @@ INCS= altivec.h \
cpuid.h \
emmintrin.h \
fma4intrin.h \
+ fmaintrin.h \
immintrin.h \
lzcntintrin.h \
mm3dnow.h \
@@ -23,11 +25,9 @@ INCS= altivec.h \
popcntintrin.h \
smmintrin.h \
tmmintrin.h \
- unwind.h \
wmmintrin.h \
x86intrin.h \
- xmmintrin.h
+ xmmintrin.h \
+ xopintrin.h
-.include <bsd.init.mk>
-.include <bsd.incs.mk>
-.include <bsd.obj.mk>
+.include <bsd.prog.mk>
diff --git a/lib/clang/include/MipsGenDisassemblerTables.inc b/lib/clang/include/MipsGenDisassemblerTables.inc
new file mode 100644
index 0000000..1308e33
--- /dev/null
+++ b/lib/clang/include/MipsGenDisassemblerTables.inc
@@ -0,0 +1,2 @@
+/* $FreeBSD$ */
+#include "MipsGenDisassemblerTables.inc.h"
diff --git a/lib/clang/include/MipsGenEDInfo.inc b/lib/clang/include/MipsGenEDInfo.inc
new file mode 100644
index 0000000..5b8099f
--- /dev/null
+++ b/lib/clang/include/MipsGenEDInfo.inc
@@ -0,0 +1,2 @@
+/* $FreeBSD$ */
+#include "MipsGenEDInfo.inc.h"
diff --git a/lib/clang/include/clang/AST/CommentNodes.inc b/lib/clang/include/clang/AST/CommentNodes.inc
new file mode 100644
index 0000000..1da6147
--- /dev/null
+++ b/lib/clang/include/clang/AST/CommentNodes.inc
@@ -0,0 +1,2 @@
+/* $FreeBSD$ */
+#include "CommentNodes.inc.h"
diff --git a/lib/clang/include/clang/Basic/DiagnosticCommentKinds.inc b/lib/clang/include/clang/Basic/DiagnosticCommentKinds.inc
new file mode 100644
index 0000000..518c3b7
--- /dev/null
+++ b/lib/clang/include/clang/Basic/DiagnosticCommentKinds.inc
@@ -0,0 +1,2 @@
+/* $FreeBSD$ */
+#include "DiagnosticCommentKinds.inc.h"
diff --git a/lib/clang/include/clang/Basic/Version.inc b/lib/clang/include/clang/Basic/Version.inc
index b263857..d04836e 100644
--- a/lib/clang/include/clang/Basic/Version.inc
+++ b/lib/clang/include/clang/Basic/Version.inc
@@ -1,10 +1,10 @@
/* $FreeBSD$ */
-#define CLANG_VERSION 3.1
+#define CLANG_VERSION 3.2
#define CLANG_VERSION_MAJOR 3
-#define CLANG_VERSION_MINOR 1
+#define CLANG_VERSION_MINOR 2
#define CLANG_VENDOR "FreeBSD "
-#define CLANG_VENDOR_SUFFIX " 20120523"
+#define CLANG_VENDOR_SUFFIX " 20120817"
-#define SVN_REVISION "156863"
+#define SVN_REVISION "162107"
diff --git a/lib/clang/include/clang/Driver/CC1Options.inc b/lib/clang/include/clang/Driver/CC1Options.inc
deleted file mode 100644
index 33029a0..0000000
--- a/lib/clang/include/clang/Driver/CC1Options.inc
+++ /dev/null
@@ -1,2 +0,0 @@
-/* $FreeBSD$ */
-#include "CC1Options.inc.h"
diff --git a/lib/clang/include/llvm/Config/AsmParsers.def b/lib/clang/include/llvm/Config/AsmParsers.def
index 0fdc4ff..024462e 100644
--- a/lib/clang/include/llvm/Config/AsmParsers.def
+++ b/lib/clang/include/llvm/Config/AsmParsers.def
@@ -1,6 +1,7 @@
/* $FreeBSD$ */
LLVM_ASM_PARSER(ARM)
+LLVM_ASM_PARSER(Mips)
LLVM_ASM_PARSER(X86)
#undef LLVM_ASM_PARSER
diff --git a/lib/clang/include/llvm/Config/Disassemblers.def b/lib/clang/include/llvm/Config/Disassemblers.def
index 3a65fa4..1b26531 100644
--- a/lib/clang/include/llvm/Config/Disassemblers.def
+++ b/lib/clang/include/llvm/Config/Disassemblers.def
@@ -1,6 +1,7 @@
/* $FreeBSD$ */
LLVM_DISASSEMBLER(ARM)
+LLVM_DISASSEMBLER(Mips)
LLVM_DISASSEMBLER(X86)
#undef LLVM_DISASSEMBLER
diff --git a/lib/clang/include/llvm/Config/config.h b/lib/clang/include/llvm/Config/config.h
index 90bee6e..15d7e2d 100644
--- a/lib/clang/include/llvm/Config/config.h
+++ b/lib/clang/include/llvm/Config/config.h
@@ -20,12 +20,15 @@
/* Define if position independent code is enabled */
#define ENABLE_PIC 0
-/* Define if timestamp information (e.g., __DATE___) is allowed */
+/* Define if timestamp information (e.g., __DATE__) is allowed */
#define ENABLE_TIMESTAMPS 0
/* Directory where gcc is installed. */
#define GCC_INSTALL_PREFIX ""
+/* Define to 1 if you have the `arc4random' function. */
+#define HAVE_ARC4RANDOM 1
+
/* Define to 1 if you have the `argz_append' function. */
/* #undef HAVE_ARGZ_APPEND */
@@ -551,6 +554,9 @@
/* Has gcc/MSVC atomic intrinsics */
#define LLVM_HAS_ATOMICS 0
+/* Host triple LLVM will be executed on */
+/* #undef LLVM_HOSTTRIPLE */
+
/* Installation directory for include files */
/* #undef LLVM_INCLUDEDIR */
@@ -630,7 +636,7 @@
#define LLVM_VERSION_MAJOR 3
/* Minor version of the LLVM API */
-#define LLVM_VERSION_MINOR 1
+#define LLVM_VERSION_MINOR 2
/* Define if the OS needs help to load dependent libraries for dlopen(). */
#define LTDL_DLOPEN_DEPLIBS 1
@@ -663,13 +669,13 @@
#define PACKAGE_NAME "LLVM"
/* Define to the full name and version of this package. */
-#define PACKAGE_STRING "LLVM 3.1"
+#define PACKAGE_STRING "LLVM 3.2svn"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "llvm"
/* Define to the version of this package. */
-#define PACKAGE_VERSION "3.1"
+#define PACKAGE_VERSION "3.2svn"
/* Define as the return type of signal handlers (`int' or `void'). */
#define RETSIGTYPE void
diff --git a/lib/clang/include/llvm/Config/llvm-config.h b/lib/clang/include/llvm/Config/llvm-config.h
index 4a8d460..ff4355c 100644
--- a/lib/clang/include/llvm/Config/llvm-config.h
+++ b/lib/clang/include/llvm/Config/llvm-config.h
@@ -42,6 +42,9 @@
/* Has gcc/MSVC atomic intrinsics */
#define LLVM_HAS_ATOMICS 0
+/* Host triple LLVM will be executed on */
+/* #undef LLVM_HOSTTRIPLE */
+
/* Installation directory for include files */
/* #undef LLVM_INCLUDEDIR */
@@ -115,6 +118,6 @@
#define LLVM_VERSION_MAJOR 3
/* Minor version of the LLVM API */
-#define LLVM_VERSION_MINOR 1
+#define LLVM_VERSION_MINOR 2
#endif
diff --git a/lib/clang/libclanganalysis/Makefile b/lib/clang/libclanganalysis/Makefile
index f45ec59..d96f5dc 100644
--- a/lib/clang/libclanganalysis/Makefile
+++ b/lib/clang/libclanganalysis/Makefile
@@ -23,6 +23,7 @@ SRCS= AnalysisDeclContext.cpp \
TGHDRS= AttrList \
Attrs \
+ CommentNodes \
DeclNodes \
DiagnosticAnalysisKinds \
DiagnosticCommonKinds \
diff --git a/lib/clang/libclangarcmigrate/Makefile b/lib/clang/libclangarcmigrate/Makefile
index d097ec4..6544805 100644
--- a/lib/clang/libclangarcmigrate/Makefile
+++ b/lib/clang/libclangarcmigrate/Makefile
@@ -26,6 +26,7 @@ SRCS= ARCMT.cpp \
TGHDRS= AttrList \
AttrParsedAttrList \
Attrs \
+ CommentNodes \
DeclNodes \
DiagnosticCommonKinds \
DiagnosticGroups \
diff --git a/lib/clang/libclangast/Makefile b/lib/clang/libclangast/Makefile
index 81812dc..a80bc7e 100644
--- a/lib/clang/libclangast/Makefile
+++ b/lib/clang/libclangast/Makefile
@@ -10,6 +10,13 @@ SRCS= APValue.cpp \
ASTImporter.cpp \
AttrImpl.cpp \
CXXInheritance.cpp \
+ Comment.cpp \
+ CommentBriefParser.cpp \
+ CommentCommandTraits.cpp \
+ CommentDumper.cpp \
+ CommentLexer.cpp \
+ CommentParser.cpp \
+ CommentSema.cpp \
Decl.cpp \
DeclBase.cpp \
DeclCXX.cpp \
@@ -35,6 +42,7 @@ SRCS= APValue.cpp \
NestedNameSpecifier.cpp \
NSAPI.cpp \
ParentMap.cpp \
+ RawCommentList.cpp \
RecordLayout.cpp \
RecordLayoutBuilder.cpp \
SelectorLocationsKind.cpp \
@@ -55,8 +63,10 @@ SRCS= APValue.cpp \
TGHDRS= AttrImpl \
AttrList \
Attrs \
+ CommentNodes \
DeclNodes \
DiagnosticASTKinds \
+ DiagnosticCommentKinds \
DiagnosticCommonKinds \
DiagnosticSemaKinds \
StmtNodes
diff --git a/lib/clang/libclangbasic/Makefile b/lib/clang/libclangbasic/Makefile
index 742cc24..f0efd74 100644
--- a/lib/clang/libclangbasic/Makefile
+++ b/lib/clang/libclangbasic/Makefile
@@ -5,6 +5,7 @@ LIB= clangbasic
SRCDIR= tools/clang/lib/Basic
SRCS= Builtins.cpp \
ConvertUTF.c \
+ ConvertUTFWrapper.cpp \
Diagnostic.cpp \
DiagnosticIDs.cpp \
FileManager.cpp \
@@ -12,6 +13,7 @@ SRCS= Builtins.cpp \
IdentifierTable.cpp \
LangOptions.cpp \
Module.cpp \
+ ObjCRuntime.cpp \
SourceLocation.cpp \
SourceManager.cpp \
TargetInfo.cpp \
@@ -22,6 +24,7 @@ SRCS= Builtins.cpp \
TGHDRS= DiagnosticAnalysisKinds \
DiagnosticASTKinds \
+ DiagnosticCommentKinds \
DiagnosticCommonKinds \
DiagnosticDriverKinds \
DiagnosticFrontendKinds \
diff --git a/lib/clang/libclangcodegen/Makefile b/lib/clang/libclangcodegen/Makefile
index bd7b171..5252e7c 100644
--- a/lib/clang/libclangcodegen/Makefile
+++ b/lib/clang/libclangcodegen/Makefile
@@ -45,6 +45,7 @@ SRCS= BackendUtil.cpp \
TGHDRS= AttrList \
Attrs \
+ CommentNodes \
DeclNodes \
DiagnosticCommonKinds \
DiagnosticFrontendKinds \
diff --git a/lib/clang/libclangdriver/Makefile b/lib/clang/libclangdriver/Makefile
index 53d49d1..4950cfa 100644
--- a/lib/clang/libclangdriver/Makefile
+++ b/lib/clang/libclangdriver/Makefile
@@ -7,7 +7,6 @@ SRCS= Action.cpp \
Arg.cpp \
ArgList.cpp \
CC1AsOptions.cpp \
- CC1Options.cpp \
Compilation.cpp \
Driver.cpp \
DriverOptions.cpp \
@@ -23,7 +22,6 @@ SRCS= Action.cpp \
WindowsToolChain.cpp
TGHDRS= CC1AsOptions \
- CC1Options \
DiagnosticCommonKinds \
DiagnosticDriverKinds \
Options
diff --git a/lib/clang/libclangedit/Makefile b/lib/clang/libclangedit/Makefile
index 147d133..a0e45a9 100644
--- a/lib/clang/libclangedit/Makefile
+++ b/lib/clang/libclangedit/Makefile
@@ -9,6 +9,7 @@ SRCS= Commit.cpp \
TGHDRS= AttrList \
Attrs \
+ CommentNodes \
DeclNodes \
StmtNodes \
DiagnosticCommonKinds
diff --git a/lib/clang/libclangfrontend/Makefile b/lib/clang/libclangfrontend/Makefile
index 0ef026b..c2813b4 100644
--- a/lib/clang/libclangfrontend/Makefile
+++ b/lib/clang/libclangfrontend/Makefile
@@ -36,7 +36,7 @@ SRCS= ASTConsumers.cpp \
TGHDRS= AttrList \
AttrParsedAttrList \
Attrs \
- CC1Options \
+ CommentNodes \
DeclNodes \
DiagnosticASTKinds \
DiagnosticCommonKinds \
diff --git a/lib/clang/libclangfrontendtool/Makefile b/lib/clang/libclangfrontendtool/Makefile
index fd52d67..f37979f 100644
--- a/lib/clang/libclangfrontendtool/Makefile
+++ b/lib/clang/libclangfrontendtool/Makefile
@@ -5,8 +5,8 @@ LIB= clangfrontendtool
SRCDIR= tools/clang/lib/FrontendTool
SRCS= ExecuteCompilerInvocation.cpp
-TGHDRS= CC1Options \
- DiagnosticCommonKinds \
- DiagnosticFrontendKinds
+TGHDRS= DiagnosticCommonKinds \
+ DiagnosticFrontendKinds \
+ Options
.include "../clang.lib.mk"
diff --git a/lib/clang/libclangparse/Makefile b/lib/clang/libclangparse/Makefile
index 1bf46a8..599a034 100644
--- a/lib/clang/libclangparse/Makefile
+++ b/lib/clang/libclangparse/Makefile
@@ -21,6 +21,7 @@ TGHDRS= AttrLateParsed \
AttrList \
AttrParsedAttrList \
Attrs \
+ CommentNodes \
DeclNodes \
DiagnosticCommonKinds \
DiagnosticParseKinds \
diff --git a/lib/clang/libclangrewrite/Makefile b/lib/clang/libclangrewrite/Makefile
index 3150b56..e165b0b 100644
--- a/lib/clang/libclangrewrite/Makefile
+++ b/lib/clang/libclangrewrite/Makefile
@@ -8,6 +8,7 @@ SRCS= DeltaTree.cpp \
FrontendActions.cpp \
HTMLPrint.cpp \
HTMLRewrite.cpp \
+ InclusionRewriter.cpp \
RewriteMacros.cpp \
RewriteModernObjC.cpp \
RewriteObjC.cpp \
@@ -19,6 +20,7 @@ SRCS= DeltaTree.cpp \
TGHDRS= AttrList \
AttrParsedAttrList \
Attrs \
+ CommentNodes \
DeclNodes \
DiagnosticCommonKinds \
DiagnosticFrontendKinds \
diff --git a/lib/clang/libclangsema/Makefile b/lib/clang/libclangsema/Makefile
index 3b2b331..83a1c56 100644
--- a/lib/clang/libclangsema/Makefile
+++ b/lib/clang/libclangsema/Makefile
@@ -50,8 +50,10 @@ TGHDRS= AttrList \
AttrParsedAttrList \
AttrTemplateInstantiate \
Attrs \
+ CommentNodes \
DeclNodes \
DiagnosticASTKinds \
+ DiagnosticCommentKinds \
DiagnosticCommonKinds \
DiagnosticParseKinds \
DiagnosticSemaKinds \
diff --git a/lib/clang/libclangserialization/Makefile b/lib/clang/libclangserialization/Makefile
index acd97ae..75f68bf 100644
--- a/lib/clang/libclangserialization/Makefile
+++ b/lib/clang/libclangserialization/Makefile
@@ -19,6 +19,7 @@ TGHDRS= AttrList \
AttrPCHWrite \
AttrParsedAttrList \
Attrs \
+ CommentNodes \
DeclNodes \
DiagnosticCommonKinds \
DiagnosticFrontendKinds \
diff --git a/lib/clang/libclangstaticanalyzercheckers/Makefile b/lib/clang/libclangstaticanalyzercheckers/Makefile
index d4eb771..1ad97b2 100644
--- a/lib/clang/libclangstaticanalyzercheckers/Makefile
+++ b/lib/clang/libclangstaticanalyzercheckers/Makefile
@@ -28,10 +28,11 @@ SRCS= AdjustedReturnValueChecker.cpp \
DebugCheckers.cpp \
DereferenceChecker.cpp \
DivZeroChecker.cpp \
+ DynamicTypePropagation.cpp \
+ ExprInspectionChecker.cpp \
FixedAddressChecker.cpp \
GenericTaintChecker.cpp \
IdempotentOperationChecker.cpp \
- IteratorsChecker.cpp \
LLVMConventionsChecker.cpp \
MacOSKeychainAPIChecker.cpp \
MacOSXAPIChecker.cpp \
@@ -56,6 +57,7 @@ SRCS= AdjustedReturnValueChecker.cpp \
StackAddrEscapeChecker.cpp \
StreamChecker.cpp \
TaintTesterChecker.cpp \
+ TraversalChecker.cpp \
UndefBranchChecker.cpp \
UndefCapturedBlockVarChecker.cpp \
UndefResultChecker.cpp \
@@ -69,6 +71,7 @@ SRCS= AdjustedReturnValueChecker.cpp \
TGHDRS= AttrList \
Attrs \
Checkers \
+ CommentNodes \
DeclNodes \
DiagnosticCommonKinds \
StmtNodes
diff --git a/lib/clang/libclangstaticanalyzercore/Makefile b/lib/clang/libclangstaticanalyzercore/Makefile
index 27cdcc6..75b3d66 100644
--- a/lib/clang/libclangstaticanalyzercore/Makefile
+++ b/lib/clang/libclangstaticanalyzercore/Makefile
@@ -4,11 +4,13 @@ LIB= clangstaticanalyzercore
SRCDIR= tools/clang/lib/StaticAnalyzer/Core
SRCS= AnalysisManager.cpp \
+ APSIntType.cpp \
BasicConstraintManager.cpp \
BasicValueFactory.cpp \
BlockCounter.cpp \
BugReporter.cpp \
BugReporterVisitors.cpp \
+ CallEvent.cpp \
Checker.cpp \
CheckerContext.cpp \
CheckerHelpers.cpp \
@@ -25,7 +27,6 @@ SRCS= AnalysisManager.cpp \
FunctionSummary.cpp \
HTMLDiagnostics.cpp \
MemRegion.cpp \
- ObjCMessage.cpp \
PathDiagnostic.cpp \
PlistDiagnostics.cpp \
ProgramState.cpp \
@@ -42,6 +43,7 @@ SRCS= AnalysisManager.cpp \
TGHDRS= AttrList \
Attrs \
+ CommentNodes \
DeclNodes \
DiagnosticCommonKinds \
StmtNodes
diff --git a/lib/clang/libclangstaticanalyzerfrontend/Makefile b/lib/clang/libclangstaticanalyzerfrontend/Makefile
index 1256743..5c7cd41 100644
--- a/lib/clang/libclangstaticanalyzerfrontend/Makefile
+++ b/lib/clang/libclangstaticanalyzerfrontend/Makefile
@@ -10,6 +10,7 @@ SRCS= AnalysisConsumer.cpp \
TGHDRS= AttrList \
Attrs \
Checkers \
+ CommentNodes \
DeclNodes \
DiagnosticCommonKinds \
DiagnosticFrontendKinds \
diff --git a/lib/clang/libllvmanalysis/Makefile b/lib/clang/libllvmanalysis/Makefile
index a05dac5..cb1e345 100644
--- a/lib/clang/libllvmanalysis/Makefile
+++ b/lib/clang/libllvmanalysis/Makefile
@@ -18,9 +18,7 @@ SRCS= AliasAnalysis.cpp \
CaptureTracking.cpp \
CodeMetrics.cpp \
ConstantFolding.cpp \
- DIBuilder.cpp \
DbgInfoPrinter.cpp \
- DebugInfo.cpp \
DomPrinter.cpp \
DominanceFrontier.cpp \
IVUsers.cpp \
diff --git a/lib/clang/libllvmcodegen/Makefile b/lib/clang/libllvmcodegen/Makefile
index 70da7da..a0db98f 100644
--- a/lib/clang/libllvmcodegen/Makefile
+++ b/lib/clang/libllvmcodegen/Makefile
@@ -15,6 +15,7 @@ SRCS= AggressiveAntiDepBreaker.cpp \
DeadMachineInstructionElim.cpp \
DFAPacketizer.cpp \
DwarfEHPrepare.cpp \
+ EarlyIfConversion.cpp \
EdgeBundles.cpp \
ExecutionDepsFix.cpp \
ExpandISelPseudos.cpp \
@@ -34,6 +35,7 @@ SRCS= AggressiveAntiDepBreaker.cpp \
LiveInterval.cpp \
LiveIntervalAnalysis.cpp \
LiveIntervalUnion.cpp \
+ LiveRegMatrix.cpp \
LiveStackAnalysis.cpp \
LiveVariables.cpp \
LiveRangeCalc.cpp \
@@ -63,6 +65,7 @@ SRCS= AggressiveAntiDepBreaker.cpp \
MachineSSAUpdater.cpp \
MachineScheduler.cpp \
MachineSink.cpp \
+ MachineTraceMetrics.cpp \
MachineVerifier.cpp \
OcamlGC.cpp \
OptimizePHIs.cpp \
@@ -81,8 +84,8 @@ SRCS= AggressiveAntiDepBreaker.cpp \
RegAllocPBQP.cpp \
RegisterClassInfo.cpp \
RegisterCoalescer.cpp \
+ RegisterPressure.cpp \
RegisterScavenging.cpp \
- RenderMachineFunction.cpp \
ScheduleDAG.cpp \
ScheduleDAGInstrs.cpp \
ScheduleDAGPrinter.cpp \
diff --git a/lib/clang/libllvmcore/Makefile b/lib/clang/libllvmcore/Makefile
index 2702b66..8de6731 100644
--- a/lib/clang/libllvmcore/Makefile
+++ b/lib/clang/libllvmcore/Makefile
@@ -10,6 +10,8 @@ SRCS= AsmWriter.cpp \
ConstantFold.cpp \
Constants.cpp \
Core.cpp \
+ DIBuilder.cpp \
+ DebugInfo.cpp \
DebugLoc.cpp \
Dominators.cpp \
Function.cpp \
@@ -30,6 +32,7 @@ SRCS= AsmWriter.cpp \
PassRegistry.cpp \
PrintModulePass.cpp \
Type.cpp \
+ TypeFinder.cpp \
Use.cpp \
User.cpp \
Value.cpp \
diff --git a/lib/clang/libllvminstrumentation/Makefile b/lib/clang/libllvminstrumentation/Makefile
index fbfa198..8e7e7a2 100644
--- a/lib/clang/libllvminstrumentation/Makefile
+++ b/lib/clang/libllvminstrumentation/Makefile
@@ -4,6 +4,7 @@ LIB= llvminstrumentation
SRCDIR= lib/Transforms/Instrumentation
SRCS= AddressSanitizer.cpp \
+ BoundsChecking.cpp \
EdgeProfiling.cpp \
FunctionBlackList.cpp \
GCOVProfiling.cpp \
diff --git a/lib/clang/libllvmmc/Makefile b/lib/clang/libllvmmc/Makefile
index 9309e97..61b8c37 100644
--- a/lib/clang/libllvmmc/Makefile
+++ b/lib/clang/libllvmmc/Makefile
@@ -12,8 +12,9 @@ SRCS= ELFObjectWriter.cpp \
MCAsmInfoDarwin.cpp \
MCAsmStreamer.cpp \
MCAssembler.cpp \
- MCCodeGenInfo.cpp \
+ MCAtom.cpp \
MCCodeEmitter.cpp \
+ MCCodeGenInfo.cpp \
MCContext.cpp \
MCDwarf.cpp \
MCELF.cpp \
@@ -23,13 +24,16 @@ SRCS= ELFObjectWriter.cpp \
MCInst.cpp \
MCInstPrinter.cpp \
MCInstrAnalysis.cpp \
+ MCLabel.cpp \
MCMachOStreamer.cpp \
MCMachObjectTargetWriter.cpp \
+ MCModule.cpp \
MCNullStreamer.cpp \
MCObjectFileInfo.cpp \
MCObjectStreamer.cpp \
MCObjectWriter.cpp \
MCPureStreamer.cpp \
+ MCRegisterInfo.cpp \
MCSection.cpp \
MCSectionCOFF.cpp \
MCSectionELF.cpp \
@@ -38,6 +42,7 @@ SRCS= ELFObjectWriter.cpp \
MCSubtargetInfo.cpp \
MCSymbol.cpp \
MCTargetAsmLexer.cpp \
+ MCValue.cpp \
MCWin64EH.cpp \
MachObjectWriter.cpp \
SubtargetFeature.cpp \
diff --git a/lib/clang/libllvmmipscodegen/Makefile b/lib/clang/libllvmmipscodegen/Makefile
index d550006..ae7d2f6 100644
--- a/lib/clang/libllvmmipscodegen/Makefile
+++ b/lib/clang/libllvmmipscodegen/Makefile
@@ -3,20 +3,25 @@
LIB= llvmmipscodegen
SRCDIR= lib/Target/Mips
-SRCS= MipsAnalyzeImmediate.cpp \
+SRCS= Mips16FrameLowering.cpp \
+ Mips16InstrInfo.cpp \
+ Mips16RegisterInfo.cpp \
+ MipsAnalyzeImmediate.cpp \
MipsAsmPrinter.cpp \
MipsCodeEmitter.cpp \
MipsDelaySlotFiller.cpp \
- MipsEmitGPRestore.cpp \
- MipsExpandPseudo.cpp \
MipsFrameLowering.cpp \
MipsISelDAGToDAG.cpp \
MipsISelLowering.cpp \
MipsInstrInfo.cpp \
MipsJITInfo.cpp \
+ MipsLongBranch.cpp \
MipsMCInstLower.cpp \
MipsMachineFunction.cpp \
MipsRegisterInfo.cpp \
+ MipsSEFrameLowering.cpp \
+ MipsSEInstrInfo.cpp \
+ MipsSERegisterInfo.cpp \
MipsSelectionDAGInfo.cpp \
MipsSubtarget.cpp \
MipsTargetMachine.cpp \
diff --git a/lib/clang/libllvmmipsdisassembler/Makefile b/lib/clang/libllvmmipsdisassembler/Makefile
new file mode 100644
index 0000000..7cdd982
--- /dev/null
+++ b/lib/clang/libllvmmipsdisassembler/Makefile
@@ -0,0 +1,15 @@
+# $FreeBSD$
+
+LIB= llvmmipsdisassembler
+
+SRCDIR= lib/Target/Mips/Disassembler
+INCDIR= lib/Target/Mips
+SRCS= MipsDisassembler.cpp
+
+TGHDRS= MipsGenDisassemblerTables \
+ MipsGenEDInfo \
+ MipsGenInstrInfo \
+ MipsGenRegisterInfo \
+ MipsGenSubtargetInfo
+
+.include "../clang.lib.mk"
diff --git a/lib/clang/libllvmmipsinstprinter/Makefile b/lib/clang/libllvmmipsinstprinter/Makefile
index 357320e..36d3b04 100644
--- a/lib/clang/libllvmmipsinstprinter/Makefile
+++ b/lib/clang/libllvmmipsinstprinter/Makefile
@@ -8,6 +8,7 @@ SRCS= MipsInstPrinter.cpp
TGHDRS= MipsGenAsmWriter \
MipsGenInstrInfo \
- MipsGenRegisterInfo
+ MipsGenRegisterInfo \
+ MipsGenSubtargetInfo
.include "../clang.lib.mk"
diff --git a/lib/clang/libllvmpowerpccodegen/Makefile b/lib/clang/libllvmpowerpccodegen/Makefile
index 1874095..a97c352 100644
--- a/lib/clang/libllvmpowerpccodegen/Makefile
+++ b/lib/clang/libllvmpowerpccodegen/Makefile
@@ -5,6 +5,7 @@ LIB= llvmpowerpccodegen
SRCDIR= lib/Target/PowerPC
SRCS= PPCAsmPrinter.cpp \
PPCBranchSelector.cpp \
+ PPCCTRLoops.cpp \
PPCCodeEmitter.cpp \
PPCFrameLowering.cpp \
PPCHazardRecognizers.cpp \
diff --git a/lib/clang/libllvmtablegen/Makefile b/lib/clang/libllvmtablegen/Makefile
index 0832498..5ac6954 100644
--- a/lib/clang/libllvmtablegen/Makefile
+++ b/lib/clang/libllvmtablegen/Makefile
@@ -6,6 +6,7 @@ SRCDIR= lib/TableGen
SRCS= Error.cpp \
Main.cpp \
Record.cpp \
+ StringMatcher.cpp \
TableGenAction.cpp \
TableGenBackend.cpp \
TGLexer.cpp \
diff --git a/lib/libarchive/Makefile b/lib/libarchive/Makefile
index 018ad32..29508ad 100644
--- a/lib/libarchive/Makefile
+++ b/lib/libarchive/Makefile
@@ -63,7 +63,10 @@ SRCS= archive_acl.c \
archive_entry_stat.c \
archive_entry_strmode.c \
archive_entry_xattr.c \
+ archive_getdate.c \
+ archive_match.c \
archive_options.c \
+ archive_pathmatch.c \
archive_ppmd7.c \
archive_rb.c \
archive_read.c \
@@ -106,6 +109,8 @@ SRCS= archive_acl.c \
archive_util.c \
archive_virtual.c \
archive_write.c \
+ archive_write_add_filter.c \
+ archive_write_disk_acl.c \
archive_write_disk_set_standard_lookup.c \
archive_write_disk_posix.c \
archive_write_open_fd.c \
diff --git a/lib/libarchive/config_freebsd.h b/lib/libarchive/config_freebsd.h
index 0a39aa6..214ffd1 100644
--- a/lib/libarchive/config_freebsd.h
+++ b/lib/libarchive/config_freebsd.h
@@ -31,10 +31,12 @@
#define HAVE_ACL_GET_LINK_NP 1
#define HAVE_ACL_GET_PERM_NP 1
#define HAVE_ACL_INIT 1
+#define HAVE_ACL_IS_TRIVIAL_NP 1
#define HAVE_ACL_PERMSET_T 1
#define HAVE_ACL_SET_FD 1
#define HAVE_ACL_SET_FD_NP 1
#define HAVE_ACL_SET_FILE 1
+#define HAVE_ACL_SET_LINK_NP 1
#define HAVE_ACL_USER 1
#define HAVE_EXTATTR_GET_FILE 1
#define HAVE_EXTATTR_LIST_FILE 1
@@ -129,7 +131,6 @@
#define HAVE_LSTAT 1
#define HAVE_LUTIMES 1
#define HAVE_MBRTOWC 1
-#define HAVE_MBSNRTOWCS 1
#define HAVE_MEMMOVE 1
#define HAVE_MEMORY_H 1
#define HAVE_MEMSET 1
@@ -206,7 +207,6 @@
#define HAVE_WCSCMP 1
#define HAVE_WCSCPY 1
#define HAVE_WCSLEN 1
-#define HAVE_WCSNRTOMBS 1
#define HAVE_WCTOMB 1
#define HAVE_WCTYPE_H 1
#define HAVE_WMEMCMP 1
diff --git a/lib/libarchive/test/Makefile b/lib/libarchive/test/Makefile
index f4865b9..5e7c7a4 100644
--- a/lib/libarchive/test/Makefile
+++ b/lib/libarchive/test/Makefile
@@ -19,13 +19,19 @@ CFLAGS+= -DHAVE_LIBLZMA=1 -DHAVE_LZMA_H=1
.PATH: ${LIBARCHIVEDIR}/libarchive/test
TESTS= \
- test_acl_freebsd.c \
+ test_acl_freebsd_nfs4.c \
+ test_acl_freebsd_posix1e.c \
test_acl_nfs4.c \
test_acl_pax.c \
test_acl_posix1e.c \
test_archive_api_feature.c \
test_archive_clear_error.c \
test_archive_crypto.c \
+ test_archive_getdate.c \
+ test_archive_match_time.c \
+ test_archive_match_owner.c \
+ test_archive_match_path.c \
+ test_archive_pathmatch.c \
test_archive_read_close_twice.c \
test_archive_read_close_twice_open_fd.c \
test_archive_read_close_twice_open_filename.c \
diff --git a/lib/libc++/Makefile b/lib/libc++/Makefile
index 1c65cc3..d1d7017 100644
--- a/lib/libc++/Makefile
+++ b/lib/libc++/Makefile
@@ -35,8 +35,27 @@ SRCS+= algorithm.cpp\
utility.cpp\
valarray.cpp
+CXXRT_SRCS+= libelftc_dem_gnu3.c\
+ terminate.cc\
+ dynamic_cast.cc\
+ memory.cc\
+ auxhelper.cc\
+ exception.cc\
+ stdexcept.cc\
+ typeinfo.cc\
+ guard.cc
+
+.for _S in ${CXXRT_SRCS}
+STATICOBJS+= cxxrt_${_S:R}.o
+cxxrt_${_S}:
+ ln -sf ${LIBCXXRTDIR}/${_S} ${.TARGET}
+.endfor
+
WARNS= 0
-CXXFLAGS+= -I${HDRDIR} -I${LIBCXXRTDIR} -std=c++0x -nostdlib -DLIBCXXRT
+CFLAGS+= -I${HDRDIR} -I${LIBCXXRTDIR} -nostdlib -DLIBCXXRT
+.if empty(CXXFLAGS:M-std=*)
+CXXFLAGS+= -std=c++0x
+.endif
DPADD= ${LIBCXXRT}
LDADD= -lcxxrt
diff --git a/lib/libc/amd64/SYS.h b/lib/libc/amd64/SYS.h
index 61d7ab4..a232383 100644
--- a/lib/libc/amd64/SYS.h
+++ b/lib/libc/amd64/SYS.h
@@ -36,38 +36,20 @@
#include <sys/syscall.h>
#include <machine/asm.h>
-#ifdef PIC
#define RSYSCALL(x) ENTRY(__CONCAT(__sys_,x)); \
.weak CNAME(x); \
.set CNAME(x),CNAME(__CONCAT(__sys_,x)); \
.weak CNAME(__CONCAT(_,x)); \
.set CNAME(__CONCAT(_,x)),CNAME(__CONCAT(__sys_,x)); \
- mov __CONCAT($SYS_,x),%rax; KERNCALL; jb 2f; ret; \
- 2: movq PIC_GOT(HIDENAME(cerror)),%rcx; jmp *%rcx; \
+ mov __CONCAT($SYS_,x),%eax; KERNCALL; \
+ jb HIDENAME(cerror); ret; \
END(__CONCAT(__sys_,x))
#define PSEUDO(x) ENTRY(__CONCAT(__sys_,x)); \
.weak CNAME(__CONCAT(_,x)); \
.set CNAME(__CONCAT(_,x)),CNAME(__CONCAT(__sys_,x)); \
- mov __CONCAT($SYS_,x),%rax; KERNCALL; jb 2f; ret ; \
- 2: movq PIC_GOT(HIDENAME(cerror)),%rcx; jmp *%rcx; \
+ mov __CONCAT($SYS_,x),%eax; KERNCALL; \
+ jb HIDENAME(cerror); ret; \
END(__CONCAT(__sys_,x))
-#else
-#define RSYSCALL(x) ENTRY(__CONCAT(__sys_,x)); \
- .weak CNAME(x); \
- .set CNAME(x),CNAME(__CONCAT(__sys_,x)); \
- .weak CNAME(__CONCAT(_,x)); \
- .set CNAME(__CONCAT(_,x)),CNAME(__CONCAT(__sys_,x)); \
- mov __CONCAT($SYS_,x),%rax; KERNCALL; jb 2f; ret; \
- 2: jmp HIDENAME(cerror); \
- END(__CONCAT(__sys_,x))
-
-#define PSEUDO(x) ENTRY(__CONCAT(__sys_,x)); \
- .weak CNAME(__CONCAT(_,x)); \
- .set CNAME(__CONCAT(_,x)),CNAME(__CONCAT(__sys_,x)); \
- mov __CONCAT($SYS_,x),%rax; KERNCALL; jb 2f; ret; \
- 2: jmp HIDENAME(cerror); \
- END(__CONCAT(__sys_,x))
-#endif
#define KERNCALL movq %rcx, %r10; syscall
diff --git a/lib/libc/amd64/Symbol.map b/lib/libc/amd64/Symbol.map
index 9997cc2..bbf6113 100644
--- a/lib/libc/amd64/Symbol.map
+++ b/lib/libc/amd64/Symbol.map
@@ -66,7 +66,6 @@ FBSDprivate_1.0 {
.curbrk;
.minbrk;
_brk;
- .cerror;
_end;
__sys_vfork;
_vfork;
diff --git a/lib/libc/amd64/gen/rfork_thread.S b/lib/libc/amd64/gen/rfork_thread.S
index 9720e08..5e764db 100644
--- a/lib/libc/amd64/gen/rfork_thread.S
+++ b/lib/libc/amd64/gen/rfork_thread.S
@@ -93,12 +93,7 @@ ENTRY(rfork_thread)
2:
popq %r12
popq %rbx
-#ifdef PIC
- movq PIC_GOT(HIDENAME(cerror)), %rdx
- jmp *%rdx
-#else
jmp HIDENAME(cerror)
-#endif
END(rfork_thread)
.section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/amd64/sys/brk.S b/lib/libc/amd64/sys/brk.S
index 2319417..4048ae6 100644
--- a/lib/libc/amd64/sys/brk.S
+++ b/lib/libc/amd64/sys/brk.S
@@ -76,12 +76,7 @@ ok:
ret
err:
addq $8, %rsp
-#ifdef PIC
- movq PIC_GOT(HIDENAME(cerror)),%rdx
- jmp *%rdx
-#else
jmp HIDENAME(cerror)
-#endif
END(brk)
.section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/amd64/sys/exect.S b/lib/libc/amd64/sys/exect.S
index 81dc8e5..04a97ed 100644
--- a/lib/libc/amd64/sys/exect.S
+++ b/lib/libc/amd64/sys/exect.S
@@ -47,12 +47,7 @@ ENTRY(exect)
pushq %r8
popfq
KERNCALL
-#ifdef PIC
- movq PIC_GOT(HIDENAME(cerror)),%rdx
- jmp *%rdx
-#else
jmp HIDENAME(cerror)
-#endif
END(exect)
.section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/amd64/sys/getcontext.S b/lib/libc/amd64/sys/getcontext.S
index ea29adb..1128796 100644
--- a/lib/libc/amd64/sys/getcontext.S
+++ b/lib/libc/amd64/sys/getcontext.S
@@ -42,16 +42,9 @@ ENTRY(__sys_getcontext)
movq (%rsp),%rsi /* save getcontext return address */
mov $SYS_getcontext,%rax
KERNCALL
- jb 1f
+ jb HIDENAME(cerror)
addq $8,%rsp /* remove stale (setcontext) return address */
jmp *%rsi /* restore return address */
-1:
-#ifdef PIC
- movq PIC_GOT(HIDENAME(cerror)),%rdx
- jmp *%rdx
-#else
- jmp HIDENAME(cerror)
-#endif
END(__sys_getcontext)
.section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/amd64/sys/pipe.S b/lib/libc/amd64/sys/pipe.S
index 59c1ac1c..8d089db 100644
--- a/lib/libc/amd64/sys/pipe.S
+++ b/lib/libc/amd64/sys/pipe.S
@@ -45,18 +45,11 @@ __FBSDID("$FreeBSD$");
ENTRY(__sys_pipe)
mov $SYS_pipe,%rax
KERNCALL
- jb 1f
+ jb HIDENAME(cerror)
movl %eax,(%rdi) /* %rdi is preserved by syscall */
movl %edx,4(%rdi)
movq $0,%rax
ret
-1:
-#ifdef PIC
- movq PIC_GOT(HIDENAME(cerror)),%rdx
- jmp *%rdx
-#else
- jmp HIDENAME(cerror)
-#endif
END(__sys_pipe)
.section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/amd64/sys/ptrace.S b/lib/libc/amd64/sys/ptrace.S
index 6235390..9c4628d 100644
--- a/lib/libc/amd64/sys/ptrace.S
+++ b/lib/libc/amd64/sys/ptrace.S
@@ -48,15 +48,8 @@ ENTRY(ptrace)
#endif
mov $SYS_ptrace,%eax
KERNCALL
- jb err
+ jb HIDENAME(cerror)
ret
-err:
-#ifdef PIC
- movq PIC_GOT(HIDENAME(cerror)),%rdx
- jmp *%rdx
-#else
- jmp HIDENAME(cerror)
-#endif
END(ptrace)
.section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/amd64/sys/reboot.S b/lib/libc/amd64/sys/reboot.S
index e79ca79..fd04ef4 100644
--- a/lib/libc/amd64/sys/reboot.S
+++ b/lib/libc/amd64/sys/reboot.S
@@ -45,15 +45,8 @@ __FBSDID("$FreeBSD$");
ENTRY(__sys_reboot)
mov $SYS_reboot,%rax
KERNCALL
- jb 1f
+ jb HIDENAME(cerror)
iretq
-1:
-#ifdef PIC
- movq PIC_GOT(HIDENAME(cerror)),%rdx
- jmp *%rdx
-#else
- jmp HIDENAME(cerror)
-#endif
END(__sys_reboot)
.section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/amd64/sys/sbrk.S b/lib/libc/amd64/sys/sbrk.S
index 3e4d8aa..0332aae 100644
--- a/lib/libc/amd64/sys/sbrk.S
+++ b/lib/libc/amd64/sys/sbrk.S
@@ -79,12 +79,7 @@ back:
ret
err:
addq $8, %rsp
-#ifdef PIC
- movq PIC_GOT(HIDENAME(cerror)),%rdx
- jmp *%rdx
-#else
jmp HIDENAME(cerror)
-#endif
END(sbrk)
.section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/amd64/sys/setlogin.S b/lib/libc/amd64/sys/setlogin.S
index 23692b9..a451491 100644
--- a/lib/libc/amd64/sys/setlogin.S
+++ b/lib/libc/amd64/sys/setlogin.S
@@ -47,7 +47,7 @@ __FBSDID("$FreeBSD$");
ENTRY(__sys_setlogin)
mov $SYS_setlogin,%rax
KERNCALL
- jb 1f
+ jb HIDENAME(cerror)
#ifdef PIC
movq PIC_GOT(CNAME(_logname_valid)),%rdx
movl $0,(%rdx)
@@ -55,13 +55,6 @@ ENTRY(__sys_setlogin)
movl $0,CNAME(_logname_valid)(%rip)
#endif
ret /* setlogin(name) */
-1:
-#ifdef PIC
- movq PIC_GOT(HIDENAME(cerror)),%rdx
- jmp *%rdx
-#else
- jmp HIDENAME(cerror)
-#endif
END(__sys_setlogin)
.section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/amd64/sys/vfork.S b/lib/libc/amd64/sys/vfork.S
index 555c3ca..2afba58 100644
--- a/lib/libc/amd64/sys/vfork.S
+++ b/lib/libc/amd64/sys/vfork.S
@@ -50,12 +50,7 @@ ENTRY(__sys_vfork)
jmp *%rsi
1:
pushq %rsi
-#ifdef PIC
- movq PIC_GOT(HIDENAME(cerror)),%rdx
- jmp *%rdx
-#else
jmp HIDENAME(cerror)
-#endif
END(__sys_vfork)
.section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/arm/gen/__aeabi_read_tp.S b/lib/libc/arm/gen/__aeabi_read_tp.S
index 228acff..c3ea99d 100644
--- a/lib/libc/arm/gen/__aeabi_read_tp.S
+++ b/lib/libc/arm/gen/__aeabi_read_tp.S
@@ -31,10 +31,16 @@ __FBSDID("$FreeBSD$");
#include <machine/sysarch.h>
ENTRY(__aeabi_read_tp)
+#ifdef ARM_TP_ADDRESS
ldr r0, .Larm_tp_address
ldr r0, [r0]
+#else
+ mrc p15, 0, r0, c13, c0, 3
+#endif
RET
+#ifdef ARM_TP_ADDRESS
.Larm_tp_address:
.word ARM_TP_ADDRESS
+#endif
diff --git a/lib/libc/arm/gen/_set_tp.c b/lib/libc/arm/gen/_set_tp.c
index 44bbdd8..97cabec 100644
--- a/lib/libc/arm/gen/_set_tp.c
+++ b/lib/libc/arm/gen/_set_tp.c
@@ -35,5 +35,9 @@ void
_set_tp(void *tp)
{
+#ifdef ARM_TP_ADDRESS
*((struct tcb **)ARM_TP_ADDRESS) = tp;
+#else
+ sysarch(ARM_SET_TP, tp);
+#endif
}
diff --git a/lib/libc/compat-43/killpg.2 b/lib/libc/compat-43/killpg.2
index b23b773..a1d52a4 100644
--- a/lib/libc/compat-43/killpg.2
+++ b/lib/libc/compat-43/killpg.2
@@ -58,11 +58,9 @@ is 0,
.Fn killpg
sends the signal to the sending process's process group.
.Pp
-The sending process and members of the process group must
-have the same effective user ID, or
-the sender must be the super-user.
-As a single special case the continue signal SIGCONT may be sent
-to any process with the same session ID as the caller.
+The sending process must be able to
+.Fn kill
+at least one process in the receiving process group.
.Sh RETURN VALUES
.Rv -std killpg
.Sh ERRORS
@@ -80,9 +78,8 @@ is not a valid signal number.
No process can be found in the process group specified by
.Fa pgrp .
.It Bq Er EPERM
-The sending process is not the super-user and one or more
-of the target processes has an effective user ID different from that
-of the sending process.
+.Fn kill
+returns EPERM for all processes in the process group.
.El
.Sh SEE ALSO
.Xr getpgrp 2 ,
diff --git a/lib/libc/gen/Makefile.inc b/lib/libc/gen/Makefile.inc
index 98e8183..2481f28 100644
--- a/lib/libc/gen/Makefile.inc
+++ b/lib/libc/gen/Makefile.inc
@@ -7,8 +7,8 @@
SRCS+= __getosreldate.c __xuname.c \
_once_stub.c _pthread_stubs.c _rand48.c _spinlock_stub.c \
_thread_init.c \
- alarm.c arc4random.c assert.c aux.c basename.c check_utility_compat.c \
- clock.c closedir.c confstr.c \
+ alarm.c arc4random.c assert.c auxv.c basename.c check_utility_compat.c \
+ clock.c clock_getcpuclockid.c closedir.c confstr.c \
crypt.c ctermid.c daemon.c devname.c dirfd.c dirname.c disklabel.c \
dlfcn.c drand48.c elf_utils.c erand48.c err.c errlst.c errno.c \
exec.c fdevname.c feature_present.c fmtcheck.c fmtmsg.c fnmatch.c \
@@ -24,7 +24,7 @@ SRCS+= __getosreldate.c __xuname.c \
lockf.c lrand48.c mrand48.c nftw.c nice.c \
nlist.c nrand48.c opendir.c \
pause.c pmadvise.c popen.c posix_spawn.c \
- psignal.c pututxline.c pw_scan.c pwcache.c \
+ psignal.c pututxline.c pw_scan.c \
raise.c readdir.c readpassphrase.c rewinddir.c \
scandir.c seed48.c seekdir.c semctl.c \
setdomainname.c sethostname.c setjmperr.c setmode.c \
@@ -36,6 +36,9 @@ SRCS+= __getosreldate.c __xuname.c \
usleep.c utime.c utxdb.c valloc.c vis.c wait.c wait3.c waitpid.c \
wordexp.c
+.PATH: ${.CURDIR}/../../contrib/libc-pwcache
+SRCS+= pwcache.c pwcache.h
+
MISRCS+=modf.c
CANCELPOINTS_SRCS=sem.c sem_new.c
@@ -52,7 +55,7 @@ SYM_MAPS+=${.CURDIR}/gen/Symbol.map
.sinclude "${.CURDIR}/${LIBC_ARCH}/gen/Makefile.inc"
MAN+= alarm.3 arc4random.3 \
- basename.3 check_utility_compat.3 clock.3 \
+ basename.3 check_utility_compat.3 clock.3 clock_getcpuclockid.3 \
confstr.3 ctermid.3 daemon.3 devname.3 directory.3 dirname.3 \
dl_iterate_phdr.3 dladdr.3 dlinfo.3 dllockinit.3 dlopen.3 \
err.3 exec.3 \
diff --git a/lib/libc/gen/Symbol.map b/lib/libc/gen/Symbol.map
index 356bee5..b4f88ae 100644
--- a/lib/libc/gen/Symbol.map
+++ b/lib/libc/gen/Symbol.map
@@ -382,10 +382,15 @@ FBSD_1.2 {
};
FBSD_1.3 {
+ clock_getcpuclockid;
dirfd;
fdlopen;
__FreeBSD_libc_enter_restricted_mode;
getcontextx;
+ gid_from_group;
+ pwcache_userdb;
+ pwcache_groupdb;
+ uid_from_user;
};
FBSDprivate_1.0 {
diff --git a/lib/libc/gen/arc4random.c b/lib/libc/gen/arc4random.c
index 46059ab..59e410b 100644
--- a/lib/libc/gen/arc4random.c
+++ b/lib/libc/gen/arc4random.c
@@ -153,7 +153,7 @@ arc4_stir(void)
if (arc4_sysctl((u_char *)&rdat, KEYSIZE) == KEYSIZE)
done = 1;
if (!done) {
- fd = _open(RANDOMDEV, O_RDONLY, 0);
+ fd = _open(RANDOMDEV, O_RDONLY | O_CLOEXEC, 0);
if (fd >= 0) {
if (_read(fd, &rdat, KEYSIZE) == KEYSIZE)
done = 1;
diff --git a/lib/libc/gen/aux.c b/lib/libc/gen/auxv.c
index 3767ac0..3767ac0 100644
--- a/lib/libc/gen/aux.c
+++ b/lib/libc/gen/auxv.c
diff --git a/lib/libc/gen/clock_getcpuclockid.3 b/lib/libc/gen/clock_getcpuclockid.3
new file mode 100644
index 0000000..3d31993
--- /dev/null
+++ b/lib/libc/gen/clock_getcpuclockid.3
@@ -0,0 +1,95 @@
+.\" Copyright (c) 2012 David Xu <davidxu@FreeBSD.org>
+.\" 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 THE AUTHOR 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 AUTHOR 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.
+.\"
+.\" Portions of this text are reprinted and reproduced in electronic form
+.\" from IEEE Std 1003.1, 2004 Edition, Standard for Information Technology --
+.\" Portable Operating System Interface (POSIX), The Open Group Base
+.\" Specifications Issue 6, Copyright (C) 2001-2004 by the Institute of
+.\" Electrical and Electronics Engineers, Inc and The Open Group. In the
+.\" event of any discrepancy between this version and the original IEEE and
+.\" The Open Group Standard, the original IEEE and The Open Group Standard is
+.\" the referee document. The original Standard can be obtained online at
+.\" http://www.opengroup.org/unix/online.html.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd August 21, 2012
+.Dt CLOCK_GETCPUCLOCKID 3
+.Os
+.Sh NAME
+.Nm clock_getcpuclockid
+.Nd access a process CPU-time clock
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In time.h
+.Ft int
+.Fn clock_getcpuclockid "pid_t pid" "clockid_t *clock_id"
+.Sh DESCRIPTION
+The
+.Fn clock_getcpuclockid
+returns the clock ID of the CPU-time clock of the process specified by
+.Fa pid .
+If the process described by
+.Fa pid
+exists and the calling process has permission, the clock ID of this
+clock will be returned in
+.Fa clock_id .
+.Pp
+If
+.Fa pid
+is zero, the
+.Fn clock_getcpuclockid
+function returns the clock ID of the CPU-time clock of the process
+making the call, in
+.Fa clock_id .
+.Sh RETURN VALUES
+Upon successful completion,
+.Fn clock_getcpuclockid
+returns zero; otherwise, an error number is returned to indicate the
+error.
+.Sh ERRORS
+The clock_getcpuclockid() function will fail if:
+.Bl -tag -width Er
+.It Bq Er EPERM
+The requesting process does not have permission to access the CPU-time
+clock for the process.
+.It Bq Er ESRCH
+No process can be found corresponding to the process specified by
+.Fa pid .
+.El
+.Sh SEE ALSO
+.Xr clock_gettime 2
+.Sh STANDARDS
+The
+.Fn clock_getcpuclockid
+function conform to
+.St -p1003.1-2001 .
+.Sh HISTORY
+The
+.Fn clock_getcpuclockid
+function first appeared in
+.Fx 10.0 .
+.Sh AUTHORS
+.An David Xu Aq davidxu@FreeBSD.org
diff --git a/lib/libc/gen/clock_getcpuclockid.c b/lib/libc/gen/clock_getcpuclockid.c
new file mode 100644
index 0000000..f26035f
--- /dev/null
+++ b/lib/libc/gen/clock_getcpuclockid.c
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2012 David Xu <davidxu@FreeBSD.org>.
+ * 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 DANIEL EISCHEN 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 AUTHOR 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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <errno.h>
+#include <time.h>
+#include <unistd.h>
+#include <sys/time.h>
+
+int
+clock_getcpuclockid(pid_t pid, clockid_t *clock_id)
+{
+ if (clock_getcpuclockid2(pid, CPUCLOCK_WHICH_PID, clock_id))
+ return (errno);
+ return (0);
+}
diff --git a/lib/libc/gen/fstab.c b/lib/libc/gen/fstab.c
index 882c57f..b68db2e 100644
--- a/lib/libc/gen/fstab.c
+++ b/lib/libc/gen/fstab.c
@@ -46,6 +46,7 @@ __FBSDID("$FreeBSD$");
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include <vis.h>
#include "un-namespace.h"
static FILE *_fs_fp;
@@ -76,7 +77,7 @@ setfstab(const char *file)
}
const char *
-getfstab (void)
+getfstab(void)
{
if (fsp_set)
@@ -86,7 +87,7 @@ getfstab (void)
}
static void
-fixfsfile()
+fixfsfile(void)
{
static char buf[sizeof(_PATH_DEV) + MNAMELEN];
struct stat sb;
@@ -108,7 +109,7 @@ fixfsfile()
}
static int
-fstabscan()
+fstabscan(void)
{
char *cp, *p;
#define MAXLINELENGTH 1024
@@ -119,7 +120,7 @@ fstabscan()
for (;;) {
if (!(p = fgets(line, sizeof(line), _fs_fp)))
- return(0);
+ return (0);
/* OLD_STYLE_FSTAB */
++LineNo;
if (*line == '#' || *line == '\n')
@@ -140,7 +141,7 @@ fstabscan()
_fs_fstab.fs_freq = atoi(cp);
if ((cp = strsep(&p, ":\n")) != NULL) {
_fs_fstab.fs_passno = atoi(cp);
- return(1);
+ return (1);
}
}
}
@@ -150,11 +151,17 @@ fstabscan()
while ((cp = strsep(&p, " \t\n")) != NULL && *cp == '\0')
;
_fs_fstab.fs_spec = cp;
- if (!_fs_fstab.fs_spec || *_fs_fstab.fs_spec == '#')
+ if (_fs_fstab.fs_spec == NULL || *_fs_fstab.fs_spec == '#')
continue;
+ if (strunvis(_fs_fstab.fs_spec, _fs_fstab.fs_spec) < 0)
+ goto bad;
while ((cp = strsep(&p, " \t\n")) != NULL && *cp == '\0')
;
_fs_fstab.fs_file = cp;
+ if (_fs_fstab.fs_file == NULL)
+ goto bad;
+ if (strunvis(_fs_fstab.fs_file, _fs_fstab.fs_file) < 0)
+ goto bad;
fixfsfile();
while ((cp = strsep(&p, " \t\n")) != NULL && *cp == '\0')
;
@@ -206,7 +213,7 @@ fstabscan()
if (typexx)
continue;
if (cp != NULL)
- return(1);
+ return (1);
bad: /* no way to distinguish between EOF and syntax error */
error(EFTYPE);
@@ -215,44 +222,45 @@ bad: /* no way to distinguish between EOF and syntax error */
}
struct fstab *
-getfsent()
+getfsent(void)
{
+
if ((!_fs_fp && !setfsent()) || !fstabscan())
- return((struct fstab *)NULL);
- return(&_fs_fstab);
+ return (NULL);
+ return (&_fs_fstab);
}
struct fstab *
-getfsspec(name)
- const char *name;
+getfsspec(const char *name)
{
+
if (setfsent())
while (fstabscan())
if (!strcmp(_fs_fstab.fs_spec, name))
- return(&_fs_fstab);
- return((struct fstab *)NULL);
+ return (&_fs_fstab);
+ return (NULL);
}
struct fstab *
-getfsfile(name)
- const char *name;
+getfsfile(const char *name)
{
+
if (setfsent())
while (fstabscan())
if (!strcmp(_fs_fstab.fs_file, name))
- return(&_fs_fstab);
- return((struct fstab *)NULL);
+ return (&_fs_fstab);
+ return (NULL);
}
-int
-setfsent()
+int
+setfsent(void)
{
int fd;
if (_fs_fp) {
rewind(_fs_fp);
LineNo = 0;
- return(1);
+ return (1);
}
if (fsp_set == 0) {
if (issetugid())
@@ -268,16 +276,17 @@ setfsent()
_fs_fp = fdopen(fd, "r");
if (_fs_fp != NULL) {
LineNo = 0;
- return(1);
+ return (1);
}
error(errno);
_close(fd);
- return(0);
+ return (0);
}
void
-endfsent()
+endfsent(void)
{
+
if (_fs_fp) {
(void)fclose(_fs_fp);
_fs_fp = NULL;
@@ -287,8 +296,7 @@ endfsent()
}
static void
-error(err)
- int err;
+error(int err)
{
char *p;
char num[30];
diff --git a/lib/libc/gen/fts-compat.c b/lib/libc/gen/fts-compat.c
index 6585416..1be41da 100644
--- a/lib/libc/gen/fts-compat.c
+++ b/lib/libc/gen/fts-compat.c
@@ -220,7 +220,8 @@ __fts_open_44bsd(argv, options, compar)
* and ".." are all fairly nasty problems. Note, if we can't get the
* descriptor we run anyway, just more slowly.
*/
- if (!ISSET(FTS_NOCHDIR) && (sp->fts_rfd = _open(".", O_RDONLY, 0)) < 0)
+ if (!ISSET(FTS_NOCHDIR) &&
+ (sp->fts_rfd = _open(".", O_RDONLY | O_CLOEXEC, 0)) < 0)
SET(FTS_NOCHDIR);
return (sp);
@@ -349,7 +350,8 @@ __fts_read_44bsd(sp)
(p->fts_info == FTS_SL || p->fts_info == FTS_SLNONE)) {
p->fts_info = fts_stat(sp, p, 1);
if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) {
- if ((p->fts_symfd = _open(".", O_RDONLY, 0)) < 0) {
+ if ((p->fts_symfd = _open(".", O_RDONLY | O_CLOEXEC,
+ 0)) < 0) {
p->fts_errno = errno;
p->fts_info = FTS_ERR;
} else
@@ -440,7 +442,7 @@ next: tmp = p;
p->fts_info = fts_stat(sp, p, 1);
if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) {
if ((p->fts_symfd =
- _open(".", O_RDONLY, 0)) < 0) {
+ _open(".", O_RDONLY | O_CLOEXEC, 0)) < 0) {
p->fts_errno = errno;
p->fts_info = FTS_ERR;
} else
@@ -581,7 +583,7 @@ __fts_children_44bsd(sp, instr)
ISSET(FTS_NOCHDIR))
return (sp->fts_child = fts_build(sp, instr));
- if ((fd = _open(".", O_RDONLY, 0)) < 0)
+ if ((fd = _open(".", O_RDONLY | O_CLOEXEC, 0)) < 0)
return (NULL);
sp->fts_child = fts_build(sp, instr);
if (fchdir(fd))
@@ -1180,7 +1182,7 @@ fts_safe_changedir(sp, p, fd, path)
newfd = fd;
if (ISSET(FTS_NOCHDIR))
return (0);
- if (fd < 0 && (newfd = _open(path, O_RDONLY, 0)) < 0)
+ if (fd < 0 && (newfd = _open(path, O_RDONLY | O_CLOEXEC, 0)) < 0)
return (-1);
if (_fstat(newfd, &sb)) {
ret = -1;
diff --git a/lib/libc/gen/fts.c b/lib/libc/gen/fts.c
index 153b8da..243320c 100644
--- a/lib/libc/gen/fts.c
+++ b/lib/libc/gen/fts.c
@@ -134,9 +134,8 @@ fts_open(argv, options, compar)
}
/* Allocate/initialize the stream. */
- if ((priv = malloc(sizeof(*priv))) == NULL)
+ if ((priv = calloc(1, sizeof(*priv))) == NULL)
return (NULL);
- memset(priv, 0, sizeof(*priv));
sp = &priv->ftsp_fts;
sp->fts_compar = compar;
sp->fts_options = options;
@@ -215,7 +214,8 @@ fts_open(argv, options, compar)
* and ".." are all fairly nasty problems. Note, if we can't get the
* descriptor we run anyway, just more slowly.
*/
- if (!ISSET(FTS_NOCHDIR) && (sp->fts_rfd = _open(".", O_RDONLY, 0)) < 0)
+ if (!ISSET(FTS_NOCHDIR) &&
+ (sp->fts_rfd = _open(".", O_RDONLY | O_CLOEXEC, 0)) < 0)
SET(FTS_NOCHDIR);
return (sp);
@@ -340,7 +340,8 @@ fts_read(FTS *sp)
(p->fts_info == FTS_SL || p->fts_info == FTS_SLNONE)) {
p->fts_info = fts_stat(sp, p, 1);
if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) {
- if ((p->fts_symfd = _open(".", O_RDONLY, 0)) < 0) {
+ if ((p->fts_symfd = _open(".", O_RDONLY | O_CLOEXEC,
+ 0)) < 0) {
p->fts_errno = errno;
p->fts_info = FTS_ERR;
} else
@@ -431,7 +432,7 @@ next: tmp = p;
p->fts_info = fts_stat(sp, p, 1);
if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) {
if ((p->fts_symfd =
- _open(".", O_RDONLY, 0)) < 0) {
+ _open(".", O_RDONLY | O_CLOEXEC, 0)) < 0) {
p->fts_errno = errno;
p->fts_info = FTS_ERR;
} else
@@ -567,7 +568,7 @@ fts_children(FTS *sp, int instr)
ISSET(FTS_NOCHDIR))
return (sp->fts_child = fts_build(sp, instr));
- if ((fd = _open(".", O_RDONLY, 0)) < 0)
+ if ((fd = _open(".", O_RDONLY | O_CLOEXEC, 0)) < 0)
return (NULL);
sp->fts_child = fts_build(sp, instr);
if (fchdir(fd)) {
@@ -1118,7 +1119,7 @@ fts_safe_changedir(FTS *sp, FTSENT *p, int fd, char *path)
newfd = fd;
if (ISSET(FTS_NOCHDIR))
return (0);
- if (fd < 0 && (newfd = _open(path, O_RDONLY, 0)) < 0)
+ if (fd < 0 && (newfd = _open(path, O_RDONLY | O_CLOEXEC, 0)) < 0)
return (-1);
if (_fstat(newfd, &sb)) {
ret = -1;
diff --git a/lib/libc/gen/ftw.c b/lib/libc/gen/ftw.c
index bfaf121..253a295 100644
--- a/lib/libc/gen/ftw.c
+++ b/lib/libc/gen/ftw.c
@@ -28,7 +28,6 @@ __FBSDID("$FreeBSD$");
#include <errno.h>
#include <fts.h>
#include <ftw.h>
-#include <limits.h>
int
ftw(const char *path, int (*fn)(const char *, const struct stat *, int),
@@ -40,7 +39,7 @@ ftw(const char *path, int (*fn)(const char *, const struct stat *, int),
int error = 0, fnflag, sverrno;
/* XXX - nfds is currently unused */
- if (nfds < 1 || nfds > OPEN_MAX) {
+ if (nfds < 1) {
errno = EINVAL;
return (-1);
}
diff --git a/lib/libc/gen/getcap.c b/lib/libc/gen/getcap.c
index 2700d3d..c321d12 100644
--- a/lib/libc/gen/getcap.c
+++ b/lib/libc/gen/getcap.c
@@ -264,7 +264,7 @@ getent(char **cap, u_int *len, char **db_array, int fd, const char *name,
*cap = cbuf;
return (retval);
} else {
- fd = _open(*db_p, O_RDONLY, 0);
+ fd = _open(*db_p, O_RDONLY | O_CLOEXEC, 0);
if (fd < 0)
continue;
myfd = 1;
diff --git a/lib/libc/gen/getcwd.c b/lib/libc/gen/getcwd.c
index 40feedf..da76d56 100644
--- a/lib/libc/gen/getcwd.c
+++ b/lib/libc/gen/getcwd.c
@@ -142,7 +142,7 @@ getcwd(pt, size)
/* Open and stat parent directory. */
fd = _openat(dir != NULL ? _dirfd(dir) : AT_FDCWD,
- "..", O_RDONLY);
+ "..", O_RDONLY | O_CLOEXEC);
if (fd == -1)
goto err;
if (dir)
diff --git a/lib/libc/gen/nftw.c b/lib/libc/gen/nftw.c
index 43110c1..a338e5a 100644
--- a/lib/libc/gen/nftw.c
+++ b/lib/libc/gen/nftw.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: nftw.c,v 1.4 2004/07/07 16:05:23 millert Exp $ */
+/* $OpenBSD: nftw.c,v 1.7 2006/03/31 19:41:44 millert Exp $ */
/*
* Copyright (c) 2003, 2004 Todd C. Miller <Todd.Miller@courtesan.com>
@@ -20,12 +20,6 @@
* Materiel Command, USAF, under agreement number F39502-99-1-0512.
*/
-#if 0
-#if defined(LIBC_SCCS) && !defined(lint)
-static const char rcsid[] = "$OpenBSD: nftw.c,v 1.4 2004/07/07 16:05:23 millert Exp $";
-#endif /* LIBC_SCCS and not lint */
-#endif
-
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
@@ -34,7 +28,6 @@ __FBSDID("$FreeBSD$");
#include <errno.h>
#include <fts.h>
#include <ftw.h>
-#include <limits.h>
int
nftw(const char *path, int (*fn)(const char *, const struct stat *, int,
@@ -47,7 +40,7 @@ nftw(const char *path, int (*fn)(const char *, const struct stat *, int,
int error = 0, ftsflags, fnflag, postorder, sverrno;
/* XXX - nfds is currently unused */
- if (nfds < 1 || nfds > OPEN_MAX) {
+ if (nfds < 1) {
errno = EINVAL;
return (-1);
}
@@ -72,6 +65,8 @@ nftw(const char *path, int (*fn)(const char *, const struct stat *, int,
continue;
fnflag = FTW_D;
break;
+ case FTS_DC:
+ continue;
case FTS_DNR:
fnflag = FTW_DNR;
break;
@@ -94,9 +89,6 @@ nftw(const char *path, int (*fn)(const char *, const struct stat *, int,
case FTS_SLNONE:
fnflag = FTW_SLN;
break;
- case FTS_DC:
- errno = ELOOP;
- /* FALLTHROUGH */
default:
error = -1;
goto done;
diff --git a/lib/libc/gen/nlist.c b/lib/libc/gen/nlist.c
index 1361af3..159731c 100644
--- a/lib/libc/gen/nlist.c
+++ b/lib/libc/gen/nlist.c
@@ -66,7 +66,7 @@ nlist(name, list)
{
int fd, n;
- fd = _open(name, O_RDONLY, 0);
+ fd = _open(name, O_RDONLY | O_CLOEXEC, 0);
if (fd < 0)
return (-1);
n = __fdnlist(fd, list);
diff --git a/lib/libc/gen/opendir.c b/lib/libc/gen/opendir.c
index 4366399..2d505fc 100644
--- a/lib/libc/gen/opendir.c
+++ b/lib/libc/gen/opendir.c
@@ -199,7 +199,8 @@ __opendir_common(int fd, const char *name, int flags)
* which has also been read -- see fts.c.
*/
if (flags & DTF_REWIND) {
- if ((fd2 = _open(name, O_RDONLY | O_DIRECTORY)) == -1) {
+ if ((fd2 = _open(name, O_RDONLY | O_DIRECTORY |
+ O_CLOEXEC)) == -1) {
saved_errno = errno;
free(buf);
free(dirp);
diff --git a/lib/libc/gen/pututxline.c b/lib/libc/gen/pututxline.c
index 98addee..555386c 100644
--- a/lib/libc/gen/pututxline.c
+++ b/lib/libc/gen/pututxline.c
@@ -47,7 +47,7 @@ futx_open(const char *file)
struct stat sb;
int fd;
- fd = _open(file, O_CREAT|O_RDWR|O_EXLOCK, 0644);
+ fd = _open(file, O_CREAT|O_RDWR|O_EXLOCK|O_CLOEXEC, 0644);
if (fd < 0)
return (NULL);
@@ -235,7 +235,7 @@ utx_lastlogin_upgrade(void)
struct stat sb;
int fd;
- fd = _open(_PATH_UTX_LASTLOGIN, O_RDWR, 0644);
+ fd = _open(_PATH_UTX_LASTLOGIN, O_RDWR|O_CLOEXEC, 0644);
if (fd < 0)
return;
@@ -269,7 +269,7 @@ utx_log_add(const struct futx *fu)
vec[1].iov_len = l;
l = htobe16(l);
- fd = _open(_PATH_UTX_LOG, O_CREAT|O_WRONLY|O_APPEND, 0644);
+ fd = _open(_PATH_UTX_LOG, O_CREAT|O_WRONLY|O_APPEND|O_CLOEXEC, 0644);
if (fd < 0)
return (-1);
if (_writev(fd, vec, 2) == -1)
diff --git a/lib/libc/gen/pwcache.3 b/lib/libc/gen/pwcache.3
deleted file mode 100644
index 3910082..0000000
--- a/lib/libc/gen/pwcache.3
+++ /dev/null
@@ -1,93 +0,0 @@
-.\" Copyright (c) 1989, 1991, 1993
-.\" The Regents of the University of California. 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.
-.\" 4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
-.\"
-.\" @(#)pwcache.3 8.1 (Berkeley) 6/9/93
-.\" $FreeBSD$
-.\"
-.Dd March 22, 2002
-.Dt PWCACHE 3
-.Os
-.Sh NAME
-.Nm pwcache
-.Nd cache password and group entries
-.Sh LIBRARY
-.Lb libc
-.Sh SYNOPSIS
-.In pwd.h
-.Ft const char *
-.Fn user_from_uid "uid_t uid" "int nouser"
-.In grp.h
-.Ft const char *
-.Fn group_from_gid "gid_t gid" "int nogroup"
-.Sh DESCRIPTION
-The
-.Fn user_from_uid
-function returns the user name associated with the argument
-.Fa uid .
-The user name is cached so that multiple calls with the same
-.Fa uid
-do not require additional calls to
-.Xr getpwuid 3 .
-If there is no user associated with the
-.Fa uid ,
-a pointer is returned
-to a string representation of the
-.Fa uid ,
-unless the argument
-.Fa nouser
-is non-zero, in which case a
-.Dv NULL
-pointer is returned.
-.Pp
-The
-.Fn group_from_gid
-function returns the group name associated with the argument
-.Fa gid .
-The group name is cached so that multiple calls with the same
-.Fa gid
-do not require additional calls to
-.Xr getgrgid 3 .
-If there is no group associated with the
-.Fa gid ,
-a pointer is returned
-to a string representation of the
-.Fa gid ,
-unless the argument
-.Fa nogroup
-is non-zero, in which case a
-.Dv NULL
-pointer is returned.
-.Sh SEE ALSO
-.Xr getgrgid 3 ,
-.Xr getpwuid 3
-.Sh HISTORY
-The
-.Fn user_from_uid
-and
-.Fn group_from_gid
-functions first appeared in
-.Bx 4.4 .
diff --git a/lib/libc/gen/pwcache.c b/lib/libc/gen/pwcache.c
deleted file mode 100644
index a8a73f1..0000000
--- a/lib/libc/gen/pwcache.c
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Copyright (c) 1989, 1993
- * The Regents of the University of California. 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.
- * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
- */
-
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)pwcache.c 8.1 (Berkeley) 6/4/93";
-#endif /* LIBC_SCCS and not lint */
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/types.h>
-
-#include <grp.h>
-#include <pwd.h>
-#include <stdio.h>
-#include <string.h>
-
-#define NCACHE 64 /* power of 2 */
-#define MASK (NCACHE - 1) /* bits to store with */
-
-const char *
-user_from_uid(uid_t uid, int nouser)
-{
- static struct ncache {
- uid_t uid;
- int found;
- char name[MAXLOGNAME];
- } c_uid[NCACHE];
- static int pwopen;
- struct passwd *pw;
- struct ncache *cp;
-
- cp = c_uid + (uid & MASK);
- if (cp->uid != uid || !*cp->name) {
- if (pwopen == 0) {
- setpassent(1);
- pwopen = 1;
- }
- pw = getpwuid(uid);
- cp->uid = uid;
- if (pw != NULL) {
- cp->found = 1;
- (void)strncpy(cp->name, pw->pw_name, MAXLOGNAME - 1);
- cp->name[MAXLOGNAME - 1] = '\0';
- } else {
- cp->found = 0;
- (void)snprintf(cp->name, MAXLOGNAME - 1, "%u", uid);
- if (nouser)
- return (NULL);
- }
- }
- return ((nouser && !cp->found) ? NULL : cp->name);
-}
-
-const char *
-group_from_gid(gid_t gid, int nogroup)
-{
- static struct ncache {
- gid_t gid;
- int found;
- char name[MAXLOGNAME];
- } c_gid[NCACHE];
- static int gropen;
- struct group *gr;
- struct ncache *cp;
-
- cp = c_gid + (gid & MASK);
- if (cp->gid != gid || !*cp->name) {
- if (gropen == 0) {
- setgroupent(1);
- gropen = 1;
- }
- gr = getgrgid(gid);
- cp->gid = gid;
- if (gr != NULL) {
- cp->found = 1;
- (void)strncpy(cp->name, gr->gr_name, MAXLOGNAME - 1);
- cp->name[MAXLOGNAME - 1] = '\0';
- } else {
- cp->found = 0;
- (void)snprintf(cp->name, MAXLOGNAME - 1, "%u", gid);
- if (nogroup)
- return (NULL);
- }
- }
- return ((nogroup && !cp->found) ? NULL : cp->name);
-}
diff --git a/lib/libc/gen/rand48.3 b/lib/libc/gen/rand48.3
index 8d325a1..c70a832 100644
--- a/lib/libc/gen/rand48.3
+++ b/lib/libc/gen/rand48.3
@@ -12,7 +12,7 @@
.\" @(#)rand48.3 V1.0 MB 8 Oct 1993
.\" $FreeBSD$
.\"
-.Dd February 2, 2010
+.Dd September 4, 2012
.Dt RAND48 3
.Os
.Sh NAME
@@ -49,6 +49,14 @@
.Ft void
.Fn lcong48 "unsigned short p[7]"
.Sh DESCRIPTION
+.Bf -symbolic
+The functions described in this manual page are not cryptographically
+secure.
+Cryptographic applications should use
+.Xr arc4random 3
+instead.
+.Ef
+.Pp
The
.Fn rand48
family of functions generates pseudo-random numbers using a linear
@@ -174,10 +182,8 @@ It is thus not possible to use values greater than 0xffff as the addend.
Note that all three methods of seeding the random number generator
always also set the multiplicand and addend for any of the six
generator calls.
-.Pp
-For a more powerful random number generator, see
-.Xr random 3 .
.Sh SEE ALSO
+.Xr arc4random 3 ,
.Xr rand 3 ,
.Xr random 3
.Sh AUTHORS
diff --git a/lib/libc/gen/readpassphrase.c b/lib/libc/gen/readpassphrase.c
index d57e703..86c7811 100644
--- a/lib/libc/gen/readpassphrase.c
+++ b/lib/libc/gen/readpassphrase.c
@@ -68,7 +68,7 @@ restart:
* stdin and write to stderr unless a tty is required.
*/
if ((flags & RPP_STDIN) ||
- (input = output = _open(_PATH_TTY, O_RDWR)) == -1) {
+ (input = output = _open(_PATH_TTY, O_RDWR | O_CLOEXEC)) == -1) {
if (flags & RPP_REQUIRE_TTY) {
errno = ENOTTY;
return(NULL);
diff --git a/lib/libc/gen/sem_new.c b/lib/libc/gen/sem_new.c
index b748b49..b11d547 100644
--- a/lib/libc/gen/sem_new.c
+++ b/lib/libc/gen/sem_new.c
@@ -198,7 +198,7 @@ _sem_open(const char *name, int flags, ...)
goto error;
}
- fd = _open(path, flags|O_RDWR, mode);
+ fd = _open(path, flags|O_RDWR|O_CLOEXEC, mode);
if (fd == -1)
goto error;
if (flock(fd, LOCK_EX) == -1)
diff --git a/lib/libc/gen/sysconf.c b/lib/libc/gen/sysconf.c
index 2d117b7..b7952b1 100644
--- a/lib/libc/gen/sysconf.c
+++ b/lib/libc/gen/sysconf.c
@@ -359,11 +359,7 @@ yesno:
return (_POSIX_CLOCK_SELECTION);
#endif
case _SC_CPUTIME:
-#if _POSIX_CPUTIME == 0
-#error "_POSIX_CPUTIME"
-#else
return (_POSIX_CPUTIME);
-#endif
#ifdef notdef
case _SC_FILE_LOCKING:
/*
diff --git a/lib/libc/gen/sysctl.c b/lib/libc/gen/sysctl.c
index fbc2c0c..a5a3d49 100644
--- a/lib/libc/gen/sysctl.c
+++ b/lib/libc/gen/sysctl.c
@@ -50,8 +50,11 @@ int
sysctl(const int *name, u_int namelen, void *oldp, size_t *oldlenp,
const void *newp, size_t newlen)
{
- if (name[0] != CTL_USER)
- return (__sysctl(name, namelen, oldp, oldlenp, newp, newlen));
+ int retval;
+
+ retval = __sysctl(name, namelen, oldp, oldlenp, newp, newlen);
+ if (retval != -1 || errno != ENOENT || name[0] != CTL_USER)
+ return (retval);
if (newp != NULL) {
errno = EPERM;
diff --git a/lib/libc/gen/syslog.c b/lib/libc/gen/syslog.c
index 99308e9..6357761 100644
--- a/lib/libc/gen/syslog.c
+++ b/lib/libc/gen/syslog.c
@@ -300,7 +300,8 @@ vsyslog(int pri, const char *fmt, va_list ap)
* Make sure the error reported is the one from the syslogd failure.
*/
if (LogStat & LOG_CONS &&
- (fd = _open(_PATH_CONSOLE, O_WRONLY|O_NONBLOCK, 0)) >= 0) {
+ (fd = _open(_PATH_CONSOLE, O_WRONLY|O_NONBLOCK|O_CLOEXEC, 0)) >=
+ 0) {
struct iovec iov[2];
struct iovec *v = iov;
diff --git a/lib/libc/i386/SYS.h b/lib/libc/i386/SYS.h
index a4a147a..355b117 100644
--- a/lib/libc/i386/SYS.h
+++ b/lib/libc/i386/SYS.h
@@ -36,21 +36,21 @@
#include <sys/syscall.h>
#include <machine/asm.h>
-#define SYSCALL(x) 2: PIC_PROLOGUE; jmp PIC_PLT(HIDENAME(cerror)); \
- ENTRY(__CONCAT(__sys_,x)); \
+#define SYSCALL(x) ENTRY(__CONCAT(__sys_,x)); \
.weak CNAME(x); \
.set CNAME(x),CNAME(__CONCAT(__sys_,x)); \
.weak CNAME(__CONCAT(_,x)); \
.set CNAME(__CONCAT(_,x)),CNAME(__CONCAT(__sys_,x)); \
- mov __CONCAT($SYS_,x),%eax; KERNCALL; jb 2b
+ mov __CONCAT($SYS_,x),%eax; KERNCALL; \
+ jb HIDENAME(cerror)
#define RSYSCALL(x) SYSCALL(x); ret; END(__CONCAT(__sys_,x))
-#define PSEUDO(x) 2: PIC_PROLOGUE; jmp PIC_PLT(HIDENAME(cerror)); \
- ENTRY(__CONCAT(__sys_,x)); \
+#define PSEUDO(x) ENTRY(__CONCAT(__sys_,x)); \
.weak CNAME(__CONCAT(_,x)); \
.set CNAME(__CONCAT(_,x)),CNAME(__CONCAT(__sys_,x)); \
- mov __CONCAT($SYS_,x),%eax; KERNCALL; jb 2b; ret; \
+ mov __CONCAT($SYS_,x),%eax; KERNCALL; \
+ jb HIDENAME(cerror); ret; \
END(__CONCAT(__sys_,x))
/* gas messes up offset -- although we don't currently need it, do for BCS */
diff --git a/lib/libc/i386/Symbol.map b/lib/libc/i386/Symbol.map
index 8a01802..78be4c4 100644
--- a/lib/libc/i386/Symbol.map
+++ b/lib/libc/i386/Symbol.map
@@ -63,7 +63,6 @@ FBSDprivate_1.0 {
__sys_vfork;
_vfork;
_end;
- .cerror;
_brk;
.curbrk;
.minbrk;
diff --git a/lib/libc/i386/gen/rfork_thread.S b/lib/libc/i386/gen/rfork_thread.S
index 3333d84..1f8181d 100644
--- a/lib/libc/i386/gen/rfork_thread.S
+++ b/lib/libc/i386/gen/rfork_thread.S
@@ -113,8 +113,7 @@ ENTRY(rfork_thread)
popl %esi
movl %ebp, %esp
popl %ebp
- PIC_PROLOGUE
- jmp PIC_PLT(HIDENAME(cerror))
+ jmp HIDENAME(cerror)
END(rfork_thread)
.section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/i386/sys/Ovfork.S b/lib/libc/i386/sys/Ovfork.S
index e3cc45d..3ef7169 100644
--- a/lib/libc/i386/sys/Ovfork.S
+++ b/lib/libc/i386/sys/Ovfork.S
@@ -50,8 +50,7 @@ ENTRY(__sys_vfork)
jmp *%ecx
1:
pushl %ecx
- PIC_PROLOGUE
- jmp PIC_PLT(HIDENAME(cerror))
+ jmp HIDENAME(cerror)
END(__sys_vfork)
.section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/i386/sys/brk.S b/lib/libc/i386/sys/brk.S
index 968e437..8a465d2 100644
--- a/lib/libc/i386/sys/brk.S
+++ b/lib/libc/i386/sys/brk.S
@@ -58,14 +58,11 @@ ENTRY(brk)
ok:
mov $SYS_break,%eax
KERNCALL
- jb err
+ jb HIDENAME(cerror)
movl 4(%esp),%eax
movl %eax,(%edx)
movl $0,%eax
ret
-err:
- PIC_PROLOGUE
- jmp PIC_PLT(HIDENAME(cerror))
#else
@@ -77,13 +74,11 @@ err:
ok:
mov $SYS_break,%eax
KERNCALL
- jb err
+ jb HIDENAME(cerror)
movl 4(%esp),%eax
movl %eax,HIDENAME(curbrk)
movl $0,%eax
ret
-err:
- jmp HIDENAME(cerror)
#endif
END(brk)
diff --git a/lib/libc/i386/sys/cerror.S b/lib/libc/i386/sys/cerror.S
index 129cc1b..ad3a033 100644
--- a/lib/libc/i386/sys/cerror.S
+++ b/lib/libc/i386/sys/cerror.S
@@ -48,13 +48,14 @@ __FBSDID("$FreeBSD$");
.globl CNAME(__error)
.type CNAME(__error),@function
HIDENAME(cerror):
- pushl %eax
#ifdef PIC
- /* The caller must execute the PIC prologue before jumping to cerror. */
+ PIC_PROLOGUE
+ pushl %eax
call PIC_PLT(CNAME(__error))
popl %ecx
PIC_EPILOGUE
#else
+ pushl %eax
call CNAME(__error)
popl %ecx
#endif
diff --git a/lib/libc/i386/sys/exect.S b/lib/libc/i386/sys/exect.S
index 3ae87b8..1378b4b 100644
--- a/lib/libc/i386/sys/exect.S
+++ b/lib/libc/i386/sys/exect.S
@@ -47,8 +47,7 @@ ENTRY(exect)
pushl %edx
popf
KERNCALL
- PIC_PROLOGUE
- jmp PIC_PLT(HIDENAME(cerror)) /* exect(file, argv, env); */
+ jmp HIDENAME(cerror) /* exect(file, argv, env); */
END(exect)
.section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/i386/sys/getcontext.S b/lib/libc/i386/sys/getcontext.S
index c24dbdc..7114689 100644
--- a/lib/libc/i386/sys/getcontext.S
+++ b/lib/libc/i386/sys/getcontext.S
@@ -42,12 +42,9 @@ ENTRY(__sys_getcontext)
movl (%esp),%ecx /* save getcontext return address */
mov $SYS_getcontext,%eax
KERNCALL
- jb 1f
+ jb HIDENAME(cerror)
addl $4,%esp /* remove stale (setcontext) return address */
jmp *%ecx /* restore return address */
-1:
- PIC_PROLOGUE
- jmp PIC_PLT(HIDENAME(cerror))
END(__sys_getcontext)
.section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/i386/sys/ptrace.S b/lib/libc/i386/sys/ptrace.S
index 6e5e885..e4bdf7c 100644
--- a/lib/libc/i386/sys/ptrace.S
+++ b/lib/libc/i386/sys/ptrace.S
@@ -50,11 +50,8 @@ ENTRY(ptrace)
#endif
mov $SYS_ptrace,%eax
KERNCALL
- jb err
+ jb HIDENAME(cerror)
ret
-err:
- PIC_PROLOGUE
- jmp PIC_PLT(HIDENAME(cerror))
END(ptrace)
.section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/i386/sys/sbrk.S b/lib/libc/i386/sys/sbrk.S
index 337087a..99fc220 100644
--- a/lib/libc/i386/sys/sbrk.S
+++ b/lib/libc/i386/sys/sbrk.S
@@ -59,7 +59,7 @@ ENTRY(sbrk)
addl %eax,4(%esp)
mov $SYS_break,%eax
KERNCALL
- jb err
+ jb HIDENAME(cerror)
PIC_PROLOGUE
movl PIC_GOT(HIDENAME(curbrk)),%edx
movl (%edx),%eax
@@ -67,9 +67,6 @@ ENTRY(sbrk)
PIC_EPILOGUE
back:
ret
-err:
- PIC_PROLOGUE
- jmp PIC_PLT(HIDENAME(cerror))
#else /* !PIC */
@@ -80,13 +77,11 @@ err:
addl %eax,4(%esp)
mov $SYS_break,%eax
KERNCALL
- jb err
+ jb HIDENAME(cerror)
movl HIDENAME(curbrk),%eax
addl %ecx,HIDENAME(curbrk)
back:
ret
-err:
- jmp HIDENAME(cerror)
#endif /* PIC */
END(sbrk)
diff --git a/lib/libc/i386/sys/syscall.S b/lib/libc/i386/sys/syscall.S
index e5d6e23..8a08631 100644
--- a/lib/libc/i386/sys/syscall.S
+++ b/lib/libc/i386/sys/syscall.S
@@ -45,11 +45,8 @@ ENTRY(syscall)
KERNCALL
push %ecx /* need to push a word to keep stack frame intact
upon return; the word must be the return address. */
- jb 1f
+ jb HIDENAME(cerror)
ret
-1:
- PIC_PROLOGUE
- jmp PIC_PLT(HIDENAME(cerror))
END(syscall)
.section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/locale/Makefile.inc b/lib/libc/locale/Makefile.inc
index adae8bd..f2161be 100644
--- a/lib/libc/locale/Makefile.inc
+++ b/lib/libc/locale/Makefile.inc
@@ -30,7 +30,8 @@ MAN+= btowc.3 \
ctype.3 digittoint.3 isalnum.3 isalpha.3 isascii.3 isblank.3 iscntrl.3 \
isdigit.3 isgraph.3 isideogram.3 islower.3 isphonogram.3 isprint.3 \
ispunct.3 isrune.3 isspace.3 isspecial.3 \
- isupper.3 iswalnum.3 isxdigit.3 localeconv.3 mblen.3 mbrlen.3 \
+ isupper.3 iswalnum.3 iswalnum_l.3 isxdigit.3 \
+ localeconv.3 mblen.3 mbrlen.3 \
mbrtowc.3 \
mbsinit.3 \
mbsrtowcs.3 mbstowcs.3 mbtowc.3 multibyte.3 \
@@ -46,6 +47,11 @@ MAN+= big5.5 euc.5 gb18030.5 gb2312.5 gbk.5 mskanji.5 utf8.5
MLINKS+=btowc.3 wctob.3
MLINKS+=isdigit.3 isnumber.3
+MLINKS+=isgraph.3 isgraph_l.3
+MLINKS+=islower.3 islower_l.3
+MLINKS+=ispunct.3 ispunct_l.3
+MLINKS+=isspace.3 isspace_l.3
+MLINKS+=nl_langinfo.3 nl_langinfo_l.3
MLINKS+=iswalnum.3 iswalpha.3 iswalnum.3 iswascii.3 iswalnum.3 iswblank.3 \
iswalnum.3 iswcntrl.3 iswalnum.3 iswdigit.3 iswalnum.3 iswgraph.3 \
iswalnum.3 iswhexnumber.3 \
@@ -53,6 +59,18 @@ MLINKS+=iswalnum.3 iswalpha.3 iswalnum.3 iswascii.3 iswalnum.3 iswblank.3 \
iswalnum.3 iswphonogram.3 iswalnum.3 iswprint.3 iswalnum.3 iswpunct.3 \
iswalnum.3 iswrune.3 iswalnum.3 iswspace.3 iswalnum.3 iswspecial.3 \
iswalnum.3 iswupper.3 iswalnum.3 iswxdigit.3
+MLINKS+=iswalnum_l.3 iswalpha_l.3 iswalnum_l.3 iswcntrl_l.3 \
+ iswalnum_l.3 iswctype_l.3 iswalnum_l.3 iswdigit_l.3 \
+ iswalnum_l.3 iswgraph_l.3 iswalnum_l.3 iswlower_l.3 \
+ iswalnum_l.3 iswprint_l.3 iswalnum_l.3 iswpunct_l.3 \
+ iswalnum_l.3 iswspace_l.3 iswalnum_l.3 iswupper_l.3 \
+ iswalnum_l.3 iswxdigit_l.3 iswalnum_l.3 towlower_l.3 \
+ iswalnum_l.3 towupper_l.3 iswalnum_l.3 wctype_l.3 \
+ iswalnum_l.3 iswblank_l.3 iswalnum_l.3 iswhexnumber_l.3 \
+ iswalnum_l.3 iswideogram_l.3 iswalnum_l.3 iswnumber_l.3 \
+ iswalnum_l.3 iswphonogram_l.3 iswalnum_l.3 iswrune_l.3 \
+ iswalnum_l.3 iswspecial_l.3 iswalnum_l.3 nextwctype_l.3 \
+ iswalnum_l.3 towctrans_l.3 iswalnum_l.3 wctrans_l.3
MLINKS+=isxdigit.3 ishexnumber.3
MLINKS+=mbsrtowcs.3 mbsnrtowcs.3
MLINKS+=wcsrtombs.3 wcsnrtombs.3
diff --git a/lib/libc/locale/isgraph.3 b/lib/libc/locale/isgraph.3
index bedf31e..95a8319 100644
--- a/lib/libc/locale/isgraph.3
+++ b/lib/libc/locale/isgraph.3
@@ -32,7 +32,7 @@
.\" @(#)isgraph.3 8.2 (Berkeley) 12/11/93
.\" $FreeBSD$
.\"
-.Dd July 17, 2005
+.Dd July 30, 2012
.Dt ISGRAPH 3
.Os
.Sh NAME
@@ -44,6 +44,8 @@
.In ctype.h
.Ft int
.Fn isgraph "int c"
+.Ft int
+.Fn isgraph_l "int c" "locale_t loc"
.Sh DESCRIPTION
The
.Fn isgraph
@@ -79,11 +81,19 @@ In the ASCII character set, this includes the following characters
.It "\&166\ ``v''" Ta "167\ ``w''" Ta "170\ ``x''" Ta "171\ ``y''" Ta "172\ ``z''"
.It "\&173\ ``{''" Ta "174\ ``|''" Ta "175\ ``}''" Ta "176\ ``~''" Ta \&
.El
+.Pp
+The
+.Fn isgraph_l
+function takes an explicit locale argument, whereas the
+.Fn isgraph
+function uses the current global or per-thread locale.
.Sh RETURN VALUES
The
.Fn isgraph
-function returns zero if the character tests false and
-returns non-zero if the character tests true.
+and
+.Fn isgraph_l
+functions return zero if the character tests false and
+return non-zero if the character tests true.
.Sh COMPATIBILITY
The
.Bx 4.4
@@ -103,3 +113,7 @@ The
.Fn isgraph
function conforms to
.St -isoC .
+The
+.Fn isgraph_l
+function conforms to
+.St -p1003.1-2008 .
diff --git a/lib/libc/locale/islower.3 b/lib/libc/locale/islower.3
index 987ff59..0b340da 100644
--- a/lib/libc/locale/islower.3
+++ b/lib/libc/locale/islower.3
@@ -32,7 +32,7 @@
.\" @(#)islower.3 8.1 (Berkeley) 6/4/93
.\" $FreeBSD$
.\"
-.Dd July 17, 2005
+.Dd July 30, 2012
.Dt ISLOWER 3
.Os
.Sh NAME
@@ -44,6 +44,8 @@
.In ctype.h
.Ft int
.Fn islower "int c"
+.Ft int
+.Fn islower_l "int c" "locale_t loc"
.Sh DESCRIPTION
The
.Fn islower
@@ -63,11 +65,18 @@ In the ASCII character set, this includes the following characters
.It "\&165\ ``u''" Ta "166\ ``v''" Ta "167\ ``w''" Ta "170\ ``x''" Ta "171\ ``y''"
.It "\&172\ ``z''" Ta \& Ta \& Ta \& Ta \&
.El
+The
+.Fn islower_l
+function takes an explicit locale argument, whereas the
+.Fn islower
+function uses the current global or per-thread locale.
.Sh RETURN VALUES
The
.Fn islower
-function returns zero if the character tests false and
-returns non-zero if the character tests true.
+and
+.Fn islower_l
+functions return zero if the character tests false and
+return non-zero if the character tests true.
.Sh COMPATIBILITY
The
.Bx 4.4
@@ -88,3 +97,7 @@ The
.Fn islower
function conforms to
.St -isoC .
+The
+.Fn islower_l
+function conforms to
+.St -p1003.1-2008 .
diff --git a/lib/libc/locale/ispunct.3 b/lib/libc/locale/ispunct.3
index 8fcfe54..c06b25d 100644
--- a/lib/libc/locale/ispunct.3
+++ b/lib/libc/locale/ispunct.3
@@ -32,7 +32,7 @@
.\" @(#)ispunct.3 8.1 (Berkeley) 6/4/93
.\" $FreeBSD$
.\"
-.Dd July 17, 2005
+.Dd July 30, 2012
.Dt ISPUNCT 3
.Os
.Sh NAME
@@ -44,6 +44,8 @@
.In ctype.h
.Ft int
.Fn ispunct "int c"
+.Ft int
+.Fn ispunct_l "int c" "locale_t loc"
.Sh DESCRIPTION
The
.Fn ispunct
@@ -69,11 +71,19 @@ In the ASCII character set, this includes the following characters
.It "\&136\ ``^''" Ta "137\ ``_''" Ta "140\ ```''" Ta "173\ ``{''" Ta "174\ ``|''"
.It "\&175\ ``}''" Ta "176\ ``~''" Ta \& Ta \& Ta \&
.El
+.Pp
+The
+.Fn ispunct_l
+function takes an explicit locale argument, whereas the
+.Fn ispunct
+function uses the current global or per-thread locale.
.Sh RETURN VALUES
The
.Fn ispunct
-function returns zero if the character tests false and
-returns non-zero if the character tests true.
+and
+.Fn ispunct_l
+functions return zero if the character tests false and
+return non-zero if the character tests true.
.Sh COMPATIBILITY
The
.Bx 4.4
@@ -93,3 +103,7 @@ The
.Fn ispunct
function conforms to
.St -isoC .
+The
+.Fn ispunct_l
+function conforms to
+.St -p1003.1-2008 .
diff --git a/lib/libc/locale/isspace.3 b/lib/libc/locale/isspace.3
index 6dfeb5f..5dfd1b6 100644
--- a/lib/libc/locale/isspace.3
+++ b/lib/libc/locale/isspace.3
@@ -32,7 +32,7 @@
.\" @(#)isspace.3 8.1 (Berkeley) 6/4/93
.\" $FreeBSD$
.\"
-.Dd July 17, 2005
+.Dd July 30, 2012
.Dt ISSPACE 3
.Os
.Sh NAME
@@ -44,6 +44,8 @@
.In ctype.h
.Ft int
.Fn isspace "int c"
+.Ft int
+.Fn isspace_l "int c" "locale_t loc"
.Sh DESCRIPTION
The
.Fn isspace
@@ -60,11 +62,19 @@ The value of the argument must be representable as an
.Vt "unsigned char"
or the value of
.Dv EOF .
+.Pp
+The
+.Fn isspace_l
+function takes an explicit locale argument, whereas the
+.Fn isspace
+function uses the current global or per-thread locale.
.Sh RETURN VALUES
The
.Fn isspace
-function returns zero if the character tests false and
-returns non-zero if the character tests true.
+and
+.Fn isspace_l
+functions return zero if the character tests false and
+return non-zero if the character tests true.
.Sh COMPATIBILITY
The
.Bx 4.4
@@ -85,3 +95,7 @@ The
.Fn isspace
function conforms to
.St -isoC .
+The
+.Fn isspace_l
+function conforms to
+.St -p1003.1-2008 .
diff --git a/lib/libc/locale/iswalnum_l.3 b/lib/libc/locale/iswalnum_l.3
new file mode 100644
index 0000000..21ee48f
--- /dev/null
+++ b/lib/libc/locale/iswalnum_l.3
@@ -0,0 +1,168 @@
+.\" Copyright (c) 2012 Isabell Long <issyl0@FreeBSD.org>
+.\" 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 THE AUTHOR 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 AUTHOR 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.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd July 25, 2012
+.Dt ISWALNUM_L 3
+.Os
+.Sh NAME
+.Nm iswalnum_l ,
+.Nm iswalpha_l ,
+.Nm iswcntrl_l ,
+.Nm iswctype_l ,
+.Nm iswdigit_l ,
+.Nm iswgraph_l ,
+.Nm iswlower_l ,
+.Nm iswprint_l ,
+.Nm iswpunct_l ,
+.Nm iswspace_l ,
+.Nm iswupper_l ,
+.Nm iswxdigit_l ,
+.Nm towlower_l ,
+.Nm towupper_l ,
+.Nm wctype_l ,
+.Nm iswblank_l ,
+.Nm iswhexnumber_l ,
+.Nm iswideogram_l ,
+.Nm iswnumber_l ,
+.Nm iswphonogram_l ,
+.Nm iswrune_l ,
+.Nm iswspecial_l ,
+.Nm nextwctype_l ,
+.Nm towctrans_l ,
+.Nm wctrans_l
+.Nd wide character classification utilities
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In wctype.h
+.Ft int
+.Fn iswalnum_l "wint_t wc" "locale_t loc"
+.Ft int
+.Fn iswalpha_l "wint_t wc" "locale_t loc"
+.Ft int
+.Fn iswcntrl_l "wint_t wc" "locale_t loc"
+.Ft int
+.Fn iswctype_l "wint_t wc" "locale_t loc"
+.Ft int
+.Fn iswdigit_l "wint_t wc" "locale_t loc"
+.Ft int
+.Fn iswgraph_l "wint_t wc" "locale_t loc"
+.Ft int
+.Fn iswlower_l "wint_t wc" "locale_t loc"
+.Ft int
+.Fn iswprint_l "wint_t wc" "locale_t loc"
+.Ft int
+.Fn iswpunct_l "wint_t wc" "locale_t loc"
+.Ft int
+.Fn iswspace_l "wint_t wc" "locale_t loc"
+.Ft int
+.Fn iswupper_l "wint_t wc" "locale_t loc"
+.Ft int
+.Fn iswxdigit_l "wint_t wc" "locale_t loc"
+.Ft wint_t
+.Fn towlower_l "wint_t wc" "locale_t loc"
+.Ft wint_t
+.Fn towupper_l "wint_t wc" "locale_t loc"
+.Ft wctype_t
+.Fn wctype_l "wint_t wc" "locale_t loc"
+.Ft int
+.Fn iswblank_l "wint_t wc" "locale_t loc"
+.Ft int
+.Fn iswhexnumber_l "wint_t wc" "locale_t loc"
+.Ft int
+.Fn iswideogram_l "wint_t wc" "locale_t loc"
+.Ft int
+.Fn iswnumber_l "wint_t wc" "locale_t loc"
+.Ft int
+.Fn iswphonogram_l "wint_t wc" "locale_t loc"
+.Ft int
+.Fn iswrune_l "wint_t wc" "locale_t loc"
+.Ft int
+.Fn iswspecial_l "wint_t wc" "locale_t loc"
+.Ft wint_t
+.Fn nextwctype_l "wint_t wc" "locale_t loc"
+.Ft wint_t
+.Fn towctrans_l "wint_t wc" "wctrans_t" "locale_t loc"
+.Ft wctrans_t
+.Fn wctrans_l "const char *" "locale_t loc"
+.Sh DESCRIPTION
+The above functions are character classification utility functions,
+for use with wide characters
+.Vt ( wchar_t
+or
+.Vt wint_t )
+in the locale
+.Fa loc .
+They behave in the same way as the versions without the _l suffix, but use
+the specified locale rather than the global or per-thread locale.
+These functions may be implemented as inline functions in
+.In wctype.h
+and as functions in the C library.
+See the specific manual pages for more information.
+.Sh RETURN VALUES
+These functions return the same things as their non-locale versions.
+If the locale is invalid, their behaviors are undefined.
+.Sh SEE ALSO
+.Xr iswalnum 3 ,
+.Xr iswalpha 3 ,
+.Xr iswblank 3 ,
+.Xr iswcntrl 3 ,
+.Xr iswctype 3 ,
+.Xr iswdigit 3 ,
+.Xr iswgraph 3 ,
+.Xr iswhexnumber 3 ,
+.Xr iswideogram 3 ,
+.Xr iswlower 3 ,
+.Xr iswnumber 3 ,
+.Xr iswphonogram 3 ,
+.Xr iswprint 3 ,
+.Xr iswpunct 3 ,
+.Xr iswrune 3 ,
+.Xr iswspace 3 ,
+.Xr iswspecial 3 ,
+.Xr iswupper 3 ,
+.Xr iswxdigit 3 ,
+.Xr nextwctype 3 ,
+.Xr towctrans 3 ,
+.Xr towlower 3 ,
+.Xr towupper 3 ,
+.Xr wctrans 3 ,
+.Xr wctype 3
+.Sh STANDARDS
+These functions conform to
+.St -p1003.1-2008 ,
+except for
+.Fn iswascii_l ,
+.Fn iswhexnumber_l ,
+.Fn iswideogram_l ,
+.Fn iswphonogram_l ,
+.Fn iswrune_l ,
+.Fn iswspecial_l
+and
+.Fn nextwctype_l
+which are
+.Fx
+extensions.
diff --git a/lib/libc/locale/ldpart.c b/lib/libc/locale/ldpart.c
index ea7b388..ccf5e7f 100644
--- a/lib/libc/locale/ldpart.c
+++ b/lib/libc/locale/ldpart.c
@@ -87,7 +87,7 @@ __part_load_locale(const char *name,
strcat(filename, name);
strcat(filename, "/");
strcat(filename, category_filename);
- if ((fd = _open(filename, O_RDONLY)) < 0)
+ if ((fd = _open(filename, O_RDONLY | O_CLOEXEC)) < 0)
return (_LDP_ERROR);
if (_fstat(fd, &st) != 0)
goto bad_locale;
diff --git a/lib/libc/locale/nl_langinfo.3 b/lib/libc/locale/nl_langinfo.3
index 789cac2..d8c01b2 100644
--- a/lib/libc/locale/nl_langinfo.3
+++ b/lib/libc/locale/nl_langinfo.3
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd May 3, 2001
+.Dd July 30, 2012
.Dt NL_LANGINFO 3
.Os
.Sh NAME
@@ -36,11 +36,16 @@
.In langinfo.h
.Ft char *
.Fn nl_langinfo "nl_item item"
+.Ft char *
+.Fn nl_langinfo_l "nl_item item" "locale_t loc"
.Sh DESCRIPTION
The
.Fn nl_langinfo
function returns a pointer to a string containing information relevant to
-the particular language or cultural area defined in the program's locale.
+the particular language or cultural area defined in the program or thread's
+locale, or in the case of
+.Fn nl_langinfo_l ,
+the locale passed as the second argument.
The manifest constant names and values of
.Fa item
are defined in
@@ -60,6 +65,9 @@ In a locale where langinfo data is not defined,
returns a pointer to the corresponding string in the
.Tn POSIX
locale.
+.Fn nl_langinfo_l
+returns the same values as
+.Fn nl_langinfo .
In all locales,
.Fn nl_langinfo
returns a pointer to an empty string if
@@ -83,6 +91,10 @@ The
.Fn nl_langinfo
function conforms to
.St -susv2 .
+The
+.Fn nl_langinfo_l
+function conforms to
+.St -p1003.1-2008 .
.Sh HISTORY
The
.Fn nl_langinfo
diff --git a/lib/libc/net/getaddrinfo.c b/lib/libc/net/getaddrinfo.c
index dc2641f..d11ff78 100644
--- a/lib/libc/net/getaddrinfo.c
+++ b/lib/libc/net/getaddrinfo.c
@@ -155,7 +155,6 @@ struct explore {
int e_af;
int e_socktype;
int e_protocol;
- const char *e_protostr;
int e_wild;
#define WILD_AF(ex) ((ex)->e_wild & 0x01)
#define WILD_SOCKTYPE(ex) ((ex)->e_wild & 0x02)
@@ -164,21 +163,21 @@ struct explore {
static const struct explore explore[] = {
#if 0
- { PF_LOCAL, ANY, ANY, NULL, 0x01 },
+ { PF_LOCAL, ANY, ANY, 0x01 },
#endif
#ifdef INET6
- { PF_INET6, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
- { PF_INET6, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
- { PF_INET6, SOCK_STREAM, IPPROTO_SCTP, "sctp", 0x03 },
- { PF_INET6, SOCK_SEQPACKET, IPPROTO_SCTP, "sctp", 0x07 },
- { PF_INET6, SOCK_RAW, ANY, NULL, 0x05 },
+ { PF_INET6, SOCK_DGRAM, IPPROTO_UDP, 0x07 },
+ { PF_INET6, SOCK_STREAM, IPPROTO_TCP, 0x07 },
+ { PF_INET6, SOCK_STREAM, IPPROTO_SCTP, 0x03 },
+ { PF_INET6, SOCK_SEQPACKET, IPPROTO_SCTP, 0x07 },
+ { PF_INET6, SOCK_RAW, ANY, 0x05 },
#endif
- { PF_INET, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
- { PF_INET, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
- { PF_INET, SOCK_STREAM, IPPROTO_SCTP, "sctp", 0x03 },
- { PF_INET, SOCK_SEQPACKET, IPPROTO_SCTP, "sctp", 0x07 },
- { PF_INET, SOCK_RAW, ANY, NULL, 0x05 },
- { -1, 0, 0, NULL, 0 },
+ { PF_INET, SOCK_DGRAM, IPPROTO_UDP, 0x07 },
+ { PF_INET, SOCK_STREAM, IPPROTO_TCP, 0x07 },
+ { PF_INET, SOCK_STREAM, IPPROTO_SCTP, 0x03 },
+ { PF_INET, SOCK_SEQPACKET, IPPROTO_SCTP, 0x07 },
+ { PF_INET, SOCK_RAW, ANY, 0x05 },
+ { -1, 0, 0, 0 },
};
#ifdef INET6
@@ -693,6 +692,8 @@ get_addrselectpolicy(struct policyhead *head)
if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), NULL, &l, NULL, 0) < 0)
return (0);
+ if (l == 0)
+ return (0);
if ((buf = malloc(l)) == NULL)
return (0);
if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), buf, &l, NULL, 0) < 0) {
diff --git a/lib/libc/net/ip6opt.c b/lib/libc/net/ip6opt.c
index d999fd4..003c625 100644
--- a/lib/libc/net/ip6opt.c
+++ b/lib/libc/net/ip6opt.c
@@ -461,7 +461,7 @@ inet6_opt_append(void *extbuf, socklen_t extlen, int offset, u_int8_t type,
int
inet6_opt_finish(void *extbuf, socklen_t extlen, int offset)
{
- int updatelen = offset > 0 ? (1 + ((offset - 1) | 7)) : 0;;
+ int updatelen = offset > 0 ? (1 + ((offset - 1) | 7)) : 0;
if (extbuf) {
u_int8_t *padp;
diff --git a/lib/libc/net/sctp_sys_calls.c b/lib/libc/net/sctp_sys_calls.c
index 3785a04..1e06f44 100644
--- a/lib/libc/net/sctp_sys_calls.c
+++ b/lib/libc/net/sctp_sys_calls.c
@@ -449,6 +449,7 @@ sctp_getpaddrs(int sd, sctp_assoc_t id, struct sockaddr **raddrs)
opt_len = (socklen_t) ((size_t)asoc + sizeof(struct sctp_getaddresses));
addrs = calloc(1, (size_t)opt_len);
if (addrs == NULL) {
+ errno = ENOMEM;
return (-1);
}
addrs->sget_assoc_id = id;
@@ -777,6 +778,7 @@ sctp_sendx(int sd, const void *msg, size_t msg_len,
}
buf = malloc(len);
if (buf == NULL) {
+ errno = ENOMEM;
return (-1);
}
aa = (int *)buf;
@@ -1052,7 +1054,7 @@ sctp_sendv(int sd,
CMSG_SPACE(sizeof(struct sctp_authinfo)) +
(size_t)addrcnt * CMSG_SPACE(sizeof(struct in6_addr)));
if (cmsgbuf == NULL) {
- errno = ENOBUFS;
+ errno = ENOMEM;
return (-1);
}
msg.msg_control = cmsgbuf;
diff --git a/lib/libc/nls/msgcat.c b/lib/libc/nls/msgcat.c
index 4532e90..44b1440 100644
--- a/lib/libc/nls/msgcat.c
+++ b/lib/libc/nls/msgcat.c
@@ -384,7 +384,7 @@ load_msgcat(const char *path, const char *name, const char *lang)
}
UNLOCK;
- if ((fd = _open(path, O_RDONLY)) == -1) {
+ if ((fd = _open(path, O_RDONLY | O_CLOEXEC)) == -1) {
SAVEFAIL(name, lang, errno);
NLRETERR(errno);
}
diff --git a/lib/libc/rpc/auth_des.c b/lib/libc/rpc/auth_des.c
index 8f363e9..1b45c3b 100644
--- a/lib/libc/rpc/auth_des.c
+++ b/lib/libc/rpc/auth_des.c
@@ -286,7 +286,7 @@ authdes_marshal(AUTH *auth, XDR *xdrs)
* Figure out the "time", accounting for any time difference
* with the server if necessary.
*/
- (void) gettimeofday(&ad->ad_timestamp, (struct timezone *)NULL);
+ (void)gettimeofday(&ad->ad_timestamp, NULL);
ad->ad_timestamp.tv_sec += ad->ad_timediff.tv_sec;
ad->ad_timestamp.tv_usec += ad->ad_timediff.tv_usec;
while (ad->ad_timestamp.tv_usec >= USEC_PER_SEC) {
diff --git a/lib/libc/rpc/auth_unix.c b/lib/libc/rpc/auth_unix.c
index c0d2548..5c138d0 100644
--- a/lib/libc/rpc/auth_unix.c
+++ b/lib/libc/rpc/auth_unix.c
@@ -94,10 +94,10 @@ struct audata {
AUTH *
authunix_create(machname, uid, gid, len, aup_gids)
char *machname;
- int uid;
- int gid;
+ u_int uid;
+ u_int gid;
int len;
- int *aup_gids;
+ u_int *aup_gids;
{
struct authunix_parms aup;
char mymem[MAX_AUTH_BYTES];
@@ -207,9 +207,8 @@ authunix_create_default()
abort();
if (ngids > NGRPS)
ngids = NGRPS;
- /* XXX: interface problem; those should all have been unsigned */
- auth = authunix_create(machname, (int)uid, (int)gid, ngids,
- (int *)gids);
+ /* XXX: interface problem; we should translate from uid_t and gid_t */
+ auth = authunix_create(machname, uid, gid, ngids, gids);
free(gids);
return (auth);
}
diff --git a/lib/libc/rpc/authunix_prot.c b/lib/libc/rpc/authunix_prot.c
index 7699e28..f80b176 100644
--- a/lib/libc/rpc/authunix_prot.c
+++ b/lib/libc/rpc/authunix_prot.c
@@ -60,19 +60,19 @@ xdr_authunix_parms(xdrs, p)
XDR *xdrs;
struct authunix_parms *p;
{
- int **paup_gids;
+ u_int **paup_gids;
assert(xdrs != NULL);
assert(p != NULL);
paup_gids = &p->aup_gids;
- if (xdr_u_long(xdrs, &(p->aup_time))
- && xdr_string(xdrs, &(p->aup_machname), MAX_MACHINE_NAME)
- && xdr_int(xdrs, &(p->aup_uid))
- && xdr_int(xdrs, &(p->aup_gid))
- && xdr_array(xdrs, (char **) paup_gids,
- &(p->aup_len), NGRPS, sizeof(int), (xdrproc_t)xdr_int) ) {
+ if (xdr_u_long(xdrs, &(p->aup_time)) &&
+ xdr_string(xdrs, &(p->aup_machname), MAX_MACHINE_NAME) &&
+ xdr_u_int(xdrs, &(p->aup_uid)) &&
+ xdr_u_int(xdrs, &(p->aup_gid)) &&
+ xdr_array(xdrs, (char **) paup_gids,
+ &(p->aup_len), NGRPS, sizeof(u_int), (xdrproc_t)xdr_u_int) ) {
return (TRUE);
}
return (FALSE);
diff --git a/lib/libc/rpc/clnt_vc.c b/lib/libc/rpc/clnt_vc.c
index 07eff46..881f84d 100644
--- a/lib/libc/rpc/clnt_vc.c
+++ b/lib/libc/rpc/clnt_vc.c
@@ -672,6 +672,10 @@ clnt_vc_destroy(cl)
if (ct->ct_addr.buf)
free(ct->ct_addr.buf);
mem_free(ct, sizeof(struct ct_data));
+ if (cl->cl_netid && cl->cl_netid[0])
+ mem_free(cl->cl_netid, strlen(cl->cl_netid) +1);
+ if (cl->cl_tp && cl->cl_tp[0])
+ mem_free(cl->cl_tp, strlen(cl->cl_tp) +1);
mem_free(cl, sizeof(CLIENT));
mutex_unlock(&clnt_fd_lock);
thr_sigsetmask(SIG_SETMASK, &(mask), NULL);
diff --git a/lib/libc/rpc/getnetpath.c b/lib/libc/rpc/getnetpath.c
index d1ea554..92eae95 100644
--- a/lib/libc/rpc/getnetpath.c
+++ b/lib/libc/rpc/getnetpath.c
@@ -99,9 +99,8 @@ setnetpath()
return (NULL);
}
if ((np_sessionp->nc_handlep = setnetconfig()) == NULL) {
- free(np_sessionp);
syslog (LOG_ERR, "rpc: failed to open " NETCONFIG);
- return (NULL);
+ goto failed;
}
np_sessionp->valid = NP_VALID;
np_sessionp->ncp_list = NULL;
diff --git a/lib/libc/rpc/rpc_generic.c b/lib/libc/rpc/rpc_generic.c
index ab259d5..0ac4597 100644
--- a/lib/libc/rpc/rpc_generic.c
+++ b/lib/libc/rpc/rpc_generic.c
@@ -269,7 +269,8 @@ __rpc_getconfip(nettype)
}
while ((nconf = getnetconfig(confighandle)) != NULL) {
if (strcmp(nconf->nc_protofmly, NC_INET) == 0) {
- if (strcmp(nconf->nc_proto, NC_TCP) == 0) {
+ if (strcmp(nconf->nc_proto, NC_TCP) == 0 &&
+ netid_tcp == NULL) {
netid_tcp = strdup(nconf->nc_netid);
if (main_thread)
netid_tcp_main = netid_tcp;
@@ -277,7 +278,8 @@ __rpc_getconfip(nettype)
thr_setspecific(tcp_key,
(void *) netid_tcp);
} else
- if (strcmp(nconf->nc_proto, NC_UDP) == 0) {
+ if (strcmp(nconf->nc_proto, NC_UDP) == 0 &&
+ netid_udp == NULL) {
netid_udp = strdup(nconf->nc_netid);
if (main_thread)
netid_udp_main = netid_udp;
diff --git a/lib/libc/rpc/rpc_soc.3 b/lib/libc/rpc/rpc_soc.3
index 8dedaa8..1af5728 100644
--- a/lib/libc/rpc/rpc_soc.3
+++ b/lib/libc/rpc/rpc_soc.3
@@ -148,7 +148,7 @@ default authentication used by
.Ft "AUTH *"
.Xc
.It Xo
-.Fn authunix_create "char *host" "int uid" "int gid" "int len" "int *aup_gids"
+.Fn authunix_create "char *host" "u_int uid" "u_int gid" "int len" "u_int *aup_gids"
.Xc
.Pp
Create and return an
diff --git a/lib/libc/rpc/svc_auth_des.c b/lib/libc/rpc/svc_auth_des.c
index de4d1b4..bd45f20 100644
--- a/lib/libc/rpc/svc_auth_des.c
+++ b/lib/libc/rpc/svc_auth_des.c
@@ -271,7 +271,7 @@ _svcauth_des(rqst, msg)
debug("timestamp before last seen");
return (AUTH_REJECTEDVERF); /* replay */
}
- (void) gettimeofday(&current, (struct timezone *)NULL);
+ (void)gettimeofday(&current, NULL);
current.tv_sec -= window; /* allow for expiration */
if (!BEFORE(&current, &timestamp)) {
debug("timestamp expired");
diff --git a/lib/libc/rpc/svc_auth_unix.c b/lib/libc/rpc/svc_auth_unix.c
index 4d6f102..20d4ecc 100644
--- a/lib/libc/rpc/svc_auth_unix.c
+++ b/lib/libc/rpc/svc_auth_unix.c
@@ -68,7 +68,7 @@ _svcauth_unix(rqst, msg)
struct area {
struct authunix_parms area_aup;
char area_machname[MAX_MACHINE_NAME+1];
- int area_gids[NGRPS];
+ u_int area_gids[NGRPS];
} *area;
u_int auth_len;
size_t str_len, gid_len;
diff --git a/lib/libc/stdio/fopen.3 b/lib/libc/stdio/fopen.3
index 64d033e..08438e7 100644
--- a/lib/libc/stdio/fopen.3
+++ b/lib/libc/stdio/fopen.3
@@ -267,7 +267,11 @@ and
.Fn freopen
functions
conform to
-.St -isoC .
+.St -isoC ,
+with the exception of the
+.Dq Li x
+mode option which conforms to
+.St -isoC-2011 .
The
.Fn fdopen
function
diff --git a/lib/libc/stdio/scanf_l.3 b/lib/libc/stdio/scanf_l.3
index 04ea5d9..405601e 100644
--- a/lib/libc/stdio/scanf_l.3
+++ b/lib/libc/stdio/scanf_l.3
@@ -57,7 +57,7 @@ The above functions scan input according to a specified
in the locale
.Fa loc .
They behave in the same way as the versions without the _l suffix, but use
-the specific locale rather than the the global or per-thread locale.
+the specific locale rather than the global or per-thread locale.
See the specific manual pages for more information.
.Sh SEE ALSO
.Xr scanf 3 ,
diff --git a/lib/libc/stdlib/at_quick_exit.3 b/lib/libc/stdlib/at_quick_exit.3
index a75c0c0..c430154 100644
--- a/lib/libc/stdlib/at_quick_exit.3
+++ b/lib/libc/stdlib/at_quick_exit.3
@@ -58,4 +58,5 @@ function returns the value 0 if successful and a non-zero value on failure.
.Sh STANDARDS
The
.Fn at_quick_exit
-function conforms to the C1x draft specification.
+function conforms to
+.St -isoC-2011 .
diff --git a/lib/libc/stdlib/getenv.c b/lib/libc/stdlib/getenv.c
index b7826d7..47963d5 100644
--- a/lib/libc/stdlib/getenv.c
+++ b/lib/libc/stdlib/getenv.c
@@ -662,6 +662,7 @@ unsetenv(const char *name)
{
int envNdx;
size_t nameLen;
+ int newEnvActive;
/* Check for malformed name. */
if (name == NULL || (nameLen = __strleneq(name)) == 0) {
@@ -674,13 +675,18 @@ unsetenv(const char *name)
return (-1);
/* Deactivate specified variable. */
+ /* Remove all occurrences. */
envNdx = envVarsTotal - 1;
- if (__findenv(name, nameLen, &envNdx, true) != NULL) {
+ newEnvActive = envActive;
+ while (__findenv(name, nameLen, &envNdx, true) != NULL) {
envVars[envNdx].active = false;
if (envVars[envNdx].putenv)
__remove_putenv(envNdx);
- __rebuild_environ(envActive - 1);
+ envNdx--;
+ newEnvActive--;
}
+ if (newEnvActive != envActive)
+ __rebuild_environ(newEnvActive);
return (0);
}
diff --git a/lib/libc/stdlib/malloc.c b/lib/libc/stdlib/malloc.c
deleted file mode 100644
index 7ef59e4..0000000
--- a/lib/libc/stdlib/malloc.c
+++ /dev/null
@@ -1,6256 +0,0 @@
-/*-
- * Copyright (C) 2006-2010 Jason Evans <jasone@FreeBSD.org>.
- * 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(s), this list of conditions and the following disclaimer as
- * the first lines of this file unmodified other than the possible
- * addition of one or more copyright notices.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice(s), this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``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 HOLDER(S) 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.
- *
- *******************************************************************************
- *
- * This allocator implementation is designed to provide scalable performance
- * for multi-threaded programs on multi-processor systems. The following
- * features are included for this purpose:
- *
- * + Multiple arenas are used if there are multiple CPUs, which reduces lock
- * contention and cache sloshing.
- *
- * + Thread-specific caching is used if there are multiple threads, which
- * reduces the amount of locking.
- *
- * + Cache line sharing between arenas is avoided for internal data
- * structures.
- *
- * + Memory is managed in chunks and runs (chunks can be split into runs),
- * rather than as individual pages. This provides a constant-time
- * mechanism for associating allocations with particular arenas.
- *
- * Allocation requests are rounded up to the nearest size class, and no record
- * of the original request size is maintained. Allocations are broken into
- * categories according to size class. Assuming runtime defaults, 4 KiB pages
- * and a 16 byte quantum on a 32-bit system, the size classes in each category
- * are as follows:
- *
- * |========================================|
- * | Category | Subcategory | Size |
- * |========================================|
- * | Small | Tiny | 2 |
- * | | | 4 |
- * | | | 8 |
- * | |------------------+----------|
- * | | Quantum-spaced | 16 |
- * | | | 32 |
- * | | | 48 |
- * | | | ... |
- * | | | 96 |
- * | | | 112 |
- * | | | 128 |
- * | |------------------+----------|
- * | | Cacheline-spaced | 192 |
- * | | | 256 |
- * | | | 320 |
- * | | | 384 |
- * | | | 448 |
- * | | | 512 |
- * | |------------------+----------|
- * | | Sub-page | 760 |
- * | | | 1024 |
- * | | | 1280 |
- * | | | ... |
- * | | | 3328 |
- * | | | 3584 |
- * | | | 3840 |
- * |========================================|
- * | Medium | 4 KiB |
- * | | 6 KiB |
- * | | 8 KiB |
- * | | ... |
- * | | 28 KiB |
- * | | 30 KiB |
- * | | 32 KiB |
- * |========================================|
- * | Large | 36 KiB |
- * | | 40 KiB |
- * | | 44 KiB |
- * | | ... |
- * | | 1012 KiB |
- * | | 1016 KiB |
- * | | 1020 KiB |
- * |========================================|
- * | Huge | 1 MiB |
- * | | 2 MiB |
- * | | 3 MiB |
- * | | ... |
- * |========================================|
- *
- * Different mechanisms are used accoding to category:
- *
- * Small/medium : Each size class is segregated into its own set of runs.
- * Each run maintains a bitmap of which regions are
- * free/allocated.
- *
- * Large : Each allocation is backed by a dedicated run. Metadata are stored
- * in the associated arena chunk header maps.
- *
- * Huge : Each allocation is backed by a dedicated contiguous set of chunks.
- * Metadata are stored in a separate red-black tree.
- *
- *******************************************************************************
- */
-
-/*
- * MALLOC_PRODUCTION disables assertions and statistics gathering. It also
- * defaults the A and J runtime options to off. These settings are appropriate
- * for production systems.
- */
-/* #define MALLOC_PRODUCTION */
-
-#ifndef MALLOC_PRODUCTION
- /*
- * MALLOC_DEBUG enables assertions and other sanity checks, and disables
- * inline functions.
- */
-# define MALLOC_DEBUG
-
- /* MALLOC_STATS enables statistics calculation. */
-# define MALLOC_STATS
-#endif
-
-/*
- * MALLOC_TINY enables support for tiny objects, which are smaller than one
- * quantum.
- */
-#define MALLOC_TINY
-
-/*
- * MALLOC_TCACHE enables a thread-specific caching layer for small and medium
- * objects. This makes it possible to allocate/deallocate objects without any
- * locking when the cache is in the steady state.
- */
-#define MALLOC_TCACHE
-
-/*
- * MALLOC_DSS enables use of sbrk(2) to allocate chunks from the data storage
- * segment (DSS). In an ideal world, this functionality would be completely
- * unnecessary, but we are burdened by history and the lack of resource limits
- * for anonymous mapped memory.
- */
-#define MALLOC_DSS
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include "libc_private.h"
-#ifdef MALLOC_DEBUG
-# define _LOCK_DEBUG
-#endif
-#include "spinlock.h"
-#include "namespace.h"
-#include <sys/mman.h>
-#include <sys/param.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <sys/sysctl.h>
-#include <sys/uio.h>
-#include <sys/ktrace.h> /* Must come after several other sys/ includes. */
-
-#include <machine/cpufunc.h>
-#include <machine/param.h>
-#include <machine/vmparam.h>
-
-#include <errno.h>
-#include <limits.h>
-#include <link.h>
-#include <pthread.h>
-#include <sched.h>
-#include <stdarg.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdint.h>
-#include <inttypes.h>
-#include <stdlib.h>
-#include <string.h>
-#include <strings.h>
-#include <unistd.h>
-
-#include "un-namespace.h"
-
-#include "libc_private.h"
-
-#define RB_COMPACT
-#include "rb.h"
-#if (defined(MALLOC_TCACHE) && defined(MALLOC_STATS))
-#include "qr.h"
-#include "ql.h"
-#endif
-
-#ifdef MALLOC_DEBUG
- /* Disable inlining to make debugging easier. */
-# define inline
-#endif
-
-/* Size of stack-allocated buffer passed to strerror_r(). */
-#define STRERROR_BUF 64
-
-/*
- * Minimum alignment of allocations is 2^LG_QUANTUM bytes.
- */
-#ifdef __i386__
-# define LG_QUANTUM 4
-# define LG_SIZEOF_PTR 2
-# define CPU_SPINWAIT __asm__ volatile("pause")
-# ifdef __clang__
-# define TLS_MODEL /* clang does not support tls_model yet */
-# else
-# define TLS_MODEL __attribute__((tls_model("initial-exec")))
-# endif
-#endif
-#ifdef __ia64__
-# define LG_QUANTUM 4
-# define LG_SIZEOF_PTR 3
-# define TLS_MODEL /* default */
-#endif
-#ifdef __alpha__
-# define LG_QUANTUM 4
-# define LG_SIZEOF_PTR 3
-# define NO_TLS
-#endif
-#ifdef __sparc64__
-# define LG_QUANTUM 4
-# define LG_SIZEOF_PTR 3
-# define TLS_MODEL __attribute__((tls_model("initial-exec")))
-#endif
-#ifdef __amd64__
-# define LG_QUANTUM 4
-# define LG_SIZEOF_PTR 3
-# define CPU_SPINWAIT __asm__ volatile("pause")
-# ifdef __clang__
-# define TLS_MODEL /* clang does not support tls_model yet */
-# else
-# define TLS_MODEL __attribute__((tls_model("initial-exec")))
-# endif
-#endif
-#ifdef __arm__
-# define LG_QUANTUM 3
-# define LG_SIZEOF_PTR 2
-# define NO_TLS
-#endif
-#ifdef __mips__
-# define LG_QUANTUM 3
-# define LG_SIZEOF_PTR 2
-# define NO_TLS
-#endif
-#ifdef __powerpc64__
-# define LG_QUANTUM 4
-# define LG_SIZEOF_PTR 3
-# define TLS_MODEL /* default */
-#elif defined(__powerpc__)
-# define LG_QUANTUM 4
-# define LG_SIZEOF_PTR 2
-# define TLS_MODEL /* default */
-#endif
-#ifdef __s390x__
-# define LG_QUANTUM 4
-#endif
-
-#define QUANTUM ((size_t)(1U << LG_QUANTUM))
-#define QUANTUM_MASK (QUANTUM - 1)
-
-#define SIZEOF_PTR (1U << LG_SIZEOF_PTR)
-
-/* sizeof(int) == (1U << LG_SIZEOF_INT). */
-#ifndef LG_SIZEOF_INT
-# define LG_SIZEOF_INT 2
-#endif
-
-/* We can't use TLS in non-PIC programs, since TLS relies on loader magic. */
-#if (!defined(PIC) && !defined(NO_TLS))
-# define NO_TLS
-#endif
-
-#ifdef NO_TLS
- /* MALLOC_TCACHE requires TLS. */
-# ifdef MALLOC_TCACHE
-# undef MALLOC_TCACHE
-# endif
-#endif
-
-/*
- * Size and alignment of memory chunks that are allocated by the OS's virtual
- * memory system.
- */
-#define LG_CHUNK_DEFAULT 22
-
-/*
- * The minimum ratio of active:dirty pages per arena is computed as:
- *
- * (nactive >> opt_lg_dirty_mult) >= ndirty
- *
- * So, supposing that opt_lg_dirty_mult is 5, there can be no less than 32
- * times as many active pages as dirty pages.
- */
-#define LG_DIRTY_MULT_DEFAULT 5
-
-/*
- * Maximum size of L1 cache line. This is used to avoid cache line aliasing.
- * In addition, this controls the spacing of cacheline-spaced size classes.
- */
-#define LG_CACHELINE 6
-#define CACHELINE ((size_t)(1U << LG_CACHELINE))
-#define CACHELINE_MASK (CACHELINE - 1)
-
-/*
- * Subpages are an artificially designated partitioning of pages. Their only
- * purpose is to support subpage-spaced size classes.
- *
- * There must be at least 4 subpages per page, due to the way size classes are
- * handled.
- */
-#define LG_SUBPAGE 8
-#define SUBPAGE ((size_t)(1U << LG_SUBPAGE))
-#define SUBPAGE_MASK (SUBPAGE - 1)
-
-#ifdef MALLOC_TINY
- /* Smallest size class to support. */
-# define LG_TINY_MIN 1
-#endif
-
-/*
- * Maximum size class that is a multiple of the quantum, but not (necessarily)
- * a power of 2. Above this size, allocations are rounded up to the nearest
- * power of 2.
- */
-#define LG_QSPACE_MAX_DEFAULT 7
-
-/*
- * Maximum size class that is a multiple of the cacheline, but not (necessarily)
- * a power of 2. Above this size, allocations are rounded up to the nearest
- * power of 2.
- */
-#define LG_CSPACE_MAX_DEFAULT 9
-
-/*
- * Maximum medium size class. This must not be more than 1/4 of a chunk
- * (LG_MEDIUM_MAX_DEFAULT <= LG_CHUNK_DEFAULT - 2).
- */
-#define LG_MEDIUM_MAX_DEFAULT 15
-
-/*
- * RUN_MAX_OVRHD indicates maximum desired run header overhead. Runs are sized
- * as small as possible such that this setting is still honored, without
- * violating other constraints. The goal is to make runs as small as possible
- * without exceeding a per run external fragmentation threshold.
- *
- * We use binary fixed point math for overhead computations, where the binary
- * point is implicitly RUN_BFP bits to the left.
- *
- * Note that it is possible to set RUN_MAX_OVRHD low enough that it cannot be
- * honored for some/all object sizes, since there is one bit of header overhead
- * per object (plus a constant). This constraint is relaxed (ignored) for runs
- * that are so small that the per-region overhead is greater than:
- *
- * (RUN_MAX_OVRHD / (reg_size << (3+RUN_BFP))
- */
-#define RUN_BFP 12
-/* \/ Implicit binary fixed point. */
-#define RUN_MAX_OVRHD 0x0000003dU
-#define RUN_MAX_OVRHD_RELAX 0x00001800U
-
-/* Put a cap on small object run size. This overrides RUN_MAX_OVRHD. */
-#define RUN_MAX_SMALL \
- (arena_maxclass <= (1U << (CHUNK_MAP_LG_PG_RANGE + PAGE_SHIFT)) \
- ? arena_maxclass : (1U << (CHUNK_MAP_LG_PG_RANGE + \
- PAGE_SHIFT)))
-
-/*
- * Hyper-threaded CPUs may need a special instruction inside spin loops in
- * order to yield to another virtual CPU. If no such instruction is defined
- * above, make CPU_SPINWAIT a no-op.
- */
-#ifndef CPU_SPINWAIT
-# define CPU_SPINWAIT
-#endif
-
-/*
- * Adaptive spinning must eventually switch to blocking, in order to avoid the
- * potential for priority inversion deadlock. Backing off past a certain point
- * can actually waste time.
- */
-#define LG_SPIN_LIMIT 11
-
-#ifdef MALLOC_TCACHE
- /*
- * Default number of cache slots for each bin in the thread cache (0:
- * disabled).
- */
-# define LG_TCACHE_NSLOTS_DEFAULT 7
- /*
- * (1U << opt_lg_tcache_gc_sweep) is the approximate number of
- * allocation events between full GC sweeps (-1: disabled). Integer
- * rounding may cause the actual number to be slightly higher, since GC is
- * performed incrementally.
- */
-# define LG_TCACHE_GC_SWEEP_DEFAULT 13
-#endif
-
-/******************************************************************************/
-
-/*
- * Mutexes based on spinlocks. We can't use normal pthread spinlocks in all
- * places, because they require malloc()ed memory, which causes bootstrapping
- * issues in some cases.
- */
-typedef struct {
- spinlock_t lock;
-} malloc_mutex_t;
-
-/* Set to true once the allocator has been initialized. */
-static bool malloc_initialized = false;
-
-/* Used to avoid initialization races. */
-static malloc_mutex_t init_lock = {_SPINLOCK_INITIALIZER};
-
-/******************************************************************************/
-/*
- * Statistics data structures.
- */
-
-#ifdef MALLOC_STATS
-
-#ifdef MALLOC_TCACHE
-typedef struct tcache_bin_stats_s tcache_bin_stats_t;
-struct tcache_bin_stats_s {
- /*
- * Number of allocation requests that corresponded to the size of this
- * bin.
- */
- uint64_t nrequests;
-};
-#endif
-
-typedef struct malloc_bin_stats_s malloc_bin_stats_t;
-struct malloc_bin_stats_s {
- /*
- * Number of allocation requests that corresponded to the size of this
- * bin.
- */
- uint64_t nrequests;
-
-#ifdef MALLOC_TCACHE
- /* Number of tcache fills from this bin. */
- uint64_t nfills;
-
- /* Number of tcache flushes to this bin. */
- uint64_t nflushes;
-#endif
-
- /* Total number of runs created for this bin's size class. */
- uint64_t nruns;
-
- /*
- * Total number of runs reused by extracting them from the runs tree for
- * this bin's size class.
- */
- uint64_t reruns;
-
- /* High-water mark for this bin. */
- size_t highruns;
-
- /* Current number of runs in this bin. */
- size_t curruns;
-};
-
-typedef struct malloc_large_stats_s malloc_large_stats_t;
-struct malloc_large_stats_s {
- /*
- * Number of allocation requests that corresponded to this size class.
- */
- uint64_t nrequests;
-
- /* High-water mark for this size class. */
- size_t highruns;
-
- /* Current number of runs of this size class. */
- size_t curruns;
-};
-
-typedef struct arena_stats_s arena_stats_t;
-struct arena_stats_s {
- /* Number of bytes currently mapped. */
- size_t mapped;
-
- /*
- * Total number of purge sweeps, total number of madvise calls made,
- * and total pages purged in order to keep dirty unused memory under
- * control.
- */
- uint64_t npurge;
- uint64_t nmadvise;
- uint64_t purged;
-
- /* Per-size-category statistics. */
- size_t allocated_small;
- uint64_t nmalloc_small;
- uint64_t ndalloc_small;
-
- size_t allocated_medium;
- uint64_t nmalloc_medium;
- uint64_t ndalloc_medium;
-
- size_t allocated_large;
- uint64_t nmalloc_large;
- uint64_t ndalloc_large;
-
- /*
- * One element for each possible size class, including sizes that
- * overlap with bin size classes. This is necessary because ipalloc()
- * sometimes has to use such large objects in order to assure proper
- * alignment.
- */
- malloc_large_stats_t *lstats;
-};
-
-typedef struct chunk_stats_s chunk_stats_t;
-struct chunk_stats_s {
- /* Number of chunks that were allocated. */
- uint64_t nchunks;
-
- /* High-water mark for number of chunks allocated. */
- size_t highchunks;
-
- /*
- * Current number of chunks allocated. This value isn't maintained for
- * any other purpose, so keep track of it in order to be able to set
- * highchunks.
- */
- size_t curchunks;
-};
-
-#endif /* #ifdef MALLOC_STATS */
-
-/******************************************************************************/
-/*
- * Extent data structures.
- */
-
-/* Tree of extents. */
-typedef struct extent_node_s extent_node_t;
-struct extent_node_s {
-#ifdef MALLOC_DSS
- /* Linkage for the size/address-ordered tree. */
- rb_node(extent_node_t) link_szad;
-#endif
-
- /* Linkage for the address-ordered tree. */
- rb_node(extent_node_t) link_ad;
-
- /* Pointer to the extent that this tree node is responsible for. */
- void *addr;
-
- /* Total region size. */
- size_t size;
-};
-typedef rb_tree(extent_node_t) extent_tree_t;
-
-/******************************************************************************/
-/*
- * Arena data structures.
- */
-
-typedef struct arena_s arena_t;
-typedef struct arena_bin_s arena_bin_t;
-
-/* Each element of the chunk map corresponds to one page within the chunk. */
-typedef struct arena_chunk_map_s arena_chunk_map_t;
-struct arena_chunk_map_s {
- /*
- * Linkage for run trees. There are two disjoint uses:
- *
- * 1) arena_t's runs_avail tree.
- * 2) arena_run_t conceptually uses this linkage for in-use non-full
- * runs, rather than directly embedding linkage.
- */
- rb_node(arena_chunk_map_t) link;
-
- /*
- * Run address (or size) and various flags are stored together. The bit
- * layout looks like (assuming 32-bit system):
- *
- * ???????? ???????? ????cccc ccccdzla
- *
- * ? : Unallocated: Run address for first/last pages, unset for internal
- * pages.
- * Small/medium: Don't care.
- * Large: Run size for first page, unset for trailing pages.
- * - : Unused.
- * c : refcount (could overflow for PAGE_SIZE >= 128 KiB)
- * d : dirty?
- * z : zeroed?
- * l : large?
- * a : allocated?
- *
- * Following are example bit patterns for the three types of runs.
- *
- * p : run page offset
- * s : run size
- * x : don't care
- * - : 0
- * [dzla] : bit set
- *
- * Unallocated:
- * ssssssss ssssssss ssss---- --------
- * xxxxxxxx xxxxxxxx xxxx---- ----d---
- * ssssssss ssssssss ssss---- -----z--
- *
- * Small/medium:
- * pppppppp ppppcccc cccccccc cccc---a
- * pppppppp ppppcccc cccccccc cccc---a
- * pppppppp ppppcccc cccccccc cccc---a
- *
- * Large:
- * ssssssss ssssssss ssss---- ------la
- * -------- -------- -------- ------la
- * -------- -------- -------- ------la
- */
- size_t bits;
-#define CHUNK_MAP_PG_MASK ((size_t)0xfff00000U)
-#define CHUNK_MAP_PG_SHIFT 20
-#define CHUNK_MAP_LG_PG_RANGE 12
-
-#define CHUNK_MAP_RC_MASK ((size_t)0xffff0U)
-#define CHUNK_MAP_RC_ONE ((size_t)0x00010U)
-
-#define CHUNK_MAP_FLAGS_MASK ((size_t)0xfU)
-#define CHUNK_MAP_DIRTY ((size_t)0x8U)
-#define CHUNK_MAP_ZEROED ((size_t)0x4U)
-#define CHUNK_MAP_LARGE ((size_t)0x2U)
-#define CHUNK_MAP_ALLOCATED ((size_t)0x1U)
-#define CHUNK_MAP_KEY (CHUNK_MAP_DIRTY | CHUNK_MAP_ALLOCATED)
-};
-typedef rb_tree(arena_chunk_map_t) arena_avail_tree_t;
-typedef rb_tree(arena_chunk_map_t) arena_run_tree_t;
-
-/* Arena chunk header. */
-typedef struct arena_chunk_s arena_chunk_t;
-struct arena_chunk_s {
- /* Arena that owns the chunk. */
- arena_t *arena;
-
- /* Linkage for the arena's chunks_dirty tree. */
- rb_node(arena_chunk_t) link_dirty;
-
- /*
- * True if the chunk is currently in the chunks_dirty tree, due to
- * having at some point contained one or more dirty pages. Removal
- * from chunks_dirty is lazy, so (dirtied && ndirty == 0) is possible.
- */
- bool dirtied;
-
- /* Number of dirty pages. */
- size_t ndirty;
-
- /* Map of pages within chunk that keeps track of free/large/small. */
- arena_chunk_map_t map[1]; /* Dynamically sized. */
-};
-typedef rb_tree(arena_chunk_t) arena_chunk_tree_t;
-
-typedef struct arena_run_s arena_run_t;
-struct arena_run_s {
-#ifdef MALLOC_DEBUG
- uint32_t magic;
-# define ARENA_RUN_MAGIC 0x384adf93
-#endif
-
- /* Bin this run is associated with. */
- arena_bin_t *bin;
-
- /* Index of first element that might have a free region. */
- unsigned regs_minelm;
-
- /* Number of free regions in run. */
- unsigned nfree;
-
- /* Bitmask of in-use regions (0: in use, 1: free). */
- unsigned regs_mask[1]; /* Dynamically sized. */
-};
-
-struct arena_bin_s {
- /*
- * Current run being used to service allocations of this bin's size
- * class.
- */
- arena_run_t *runcur;
-
- /*
- * Tree of non-full runs. This tree is used when looking for an
- * existing run when runcur is no longer usable. We choose the
- * non-full run that is lowest in memory; this policy tends to keep
- * objects packed well, and it can also help reduce the number of
- * almost-empty chunks.
- */
- arena_run_tree_t runs;
-
- /* Size of regions in a run for this bin's size class. */
- size_t reg_size;
-
- /* Total size of a run for this bin's size class. */
- size_t run_size;
-
- /* Total number of regions in a run for this bin's size class. */
- uint32_t nregs;
-
- /* Number of elements in a run's regs_mask for this bin's size class. */
- uint32_t regs_mask_nelms;
-
- /* Offset of first region in a run for this bin's size class. */
- uint32_t reg0_offset;
-
-#ifdef MALLOC_STATS
- /* Bin statistics. */
- malloc_bin_stats_t stats;
-#endif
-};
-
-#ifdef MALLOC_TCACHE
-typedef struct tcache_s tcache_t;
-#endif
-
-struct arena_s {
-#ifdef MALLOC_DEBUG
- uint32_t magic;
-# define ARENA_MAGIC 0x947d3d24
-#endif
-
- /* All operations on this arena require that lock be locked. */
- pthread_mutex_t lock;
-
-#ifdef MALLOC_STATS
- arena_stats_t stats;
-# ifdef MALLOC_TCACHE
- /*
- * List of tcaches for extant threads associated with this arena.
- * Stats from these are merged incrementally, and at exit.
- */
- ql_head(tcache_t) tcache_ql;
-# endif
-#endif
-
- /* Tree of dirty-page-containing chunks this arena manages. */
- arena_chunk_tree_t chunks_dirty;
-
- /*
- * In order to avoid rapid chunk allocation/deallocation when an arena
- * oscillates right on the cusp of needing a new chunk, cache the most
- * recently freed chunk. The spare is left in the arena's chunk trees
- * until it is deleted.
- *
- * There is one spare chunk per arena, rather than one spare total, in
- * order to avoid interactions between multiple threads that could make
- * a single spare inadequate.
- */
- arena_chunk_t *spare;
-
- /* Number of pages in active runs. */
- size_t nactive;
-
- /*
- * Current count of pages within unused runs that are potentially
- * dirty, and for which madvise(... MADV_FREE) has not been called. By
- * tracking this, we can institute a limit on how much dirty unused
- * memory is mapped for each arena.
- */
- size_t ndirty;
-
- /*
- * Size/address-ordered tree of this arena's available runs. This tree
- * is used for first-best-fit run allocation.
- */
- arena_avail_tree_t runs_avail;
-
- /*
- * bins is used to store trees of free regions of the following sizes,
- * assuming a 16-byte quantum, 4 KiB page size, and default
- * MALLOC_OPTIONS.
- *
- * bins[i] | size |
- * --------+--------+
- * 0 | 2 |
- * 1 | 4 |
- * 2 | 8 |
- * --------+--------+
- * 3 | 16 |
- * 4 | 32 |
- * 5 | 48 |
- * : :
- * 8 | 96 |
- * 9 | 112 |
- * 10 | 128 |
- * --------+--------+
- * 11 | 192 |
- * 12 | 256 |
- * 13 | 320 |
- * 14 | 384 |
- * 15 | 448 |
- * 16 | 512 |
- * --------+--------+
- * 17 | 768 |
- * 18 | 1024 |
- * 19 | 1280 |
- * : :
- * 27 | 3328 |
- * 28 | 3584 |
- * 29 | 3840 |
- * --------+--------+
- * 30 | 4 KiB |
- * 31 | 6 KiB |
- * 33 | 8 KiB |
- * : :
- * 43 | 28 KiB |
- * 44 | 30 KiB |
- * 45 | 32 KiB |
- * --------+--------+
- */
- arena_bin_t bins[1]; /* Dynamically sized. */
-};
-
-/******************************************************************************/
-/*
- * Thread cache data structures.
- */
-
-#ifdef MALLOC_TCACHE
-typedef struct tcache_bin_s tcache_bin_t;
-struct tcache_bin_s {
-# ifdef MALLOC_STATS
- tcache_bin_stats_t tstats;
-# endif
- unsigned low_water; /* Min # cached since last GC. */
- unsigned high_water; /* Max # cached since last GC. */
- unsigned ncached; /* # of cached objects. */
- void *slots[1]; /* Dynamically sized. */
-};
-
-struct tcache_s {
-# ifdef MALLOC_STATS
- ql_elm(tcache_t) link; /* Used for aggregating stats. */
-# endif
- arena_t *arena; /* This thread's arena. */
- unsigned ev_cnt; /* Event count since incremental GC. */
- unsigned next_gc_bin; /* Next bin to GC. */
- tcache_bin_t *tbins[1]; /* Dynamically sized. */
-};
-#endif
-
-/******************************************************************************/
-/*
- * Data.
- */
-
-/* Number of CPUs. */
-static unsigned ncpus;
-
-/* Various bin-related settings. */
-#ifdef MALLOC_TINY /* Number of (2^n)-spaced tiny bins. */
-# define ntbins ((unsigned)(LG_QUANTUM - LG_TINY_MIN))
-#else
-# define ntbins 0
-#endif
-static unsigned nqbins; /* Number of quantum-spaced bins. */
-static unsigned ncbins; /* Number of cacheline-spaced bins. */
-static unsigned nsbins; /* Number of subpage-spaced bins. */
-static unsigned nmbins; /* Number of medium bins. */
-static unsigned nbins;
-static unsigned mbin0; /* mbin offset (nbins - nmbins). */
-#ifdef MALLOC_TINY
-# define tspace_max ((size_t)(QUANTUM >> 1))
-#endif
-#define qspace_min QUANTUM
-static size_t qspace_max;
-static size_t cspace_min;
-static size_t cspace_max;
-static size_t sspace_min;
-static size_t sspace_max;
-#define small_maxclass sspace_max
-#define medium_min PAGE_SIZE
-static size_t medium_max;
-#define bin_maxclass medium_max
-
-/*
- * Soft limit on the number of medium size classes. Spacing between medium
- * size classes never exceeds pagesize, which can force more than NBINS_MAX
- * medium size classes.
- */
-#define NMBINS_MAX 16
-/* Spacing between medium size classes. */
-static size_t lg_mspace;
-static size_t mspace_mask;
-
-static uint8_t const *small_size2bin;
-/*
- * const_small_size2bin is a static constant lookup table that in the common
- * case can be used as-is for small_size2bin. For dynamically linked programs,
- * this avoids a page of memory overhead per process.
- */
-#define S2B_1(i) i,
-#define S2B_2(i) S2B_1(i) S2B_1(i)
-#define S2B_4(i) S2B_2(i) S2B_2(i)
-#define S2B_8(i) S2B_4(i) S2B_4(i)
-#define S2B_16(i) S2B_8(i) S2B_8(i)
-#define S2B_32(i) S2B_16(i) S2B_16(i)
-#define S2B_64(i) S2B_32(i) S2B_32(i)
-#define S2B_128(i) S2B_64(i) S2B_64(i)
-#define S2B_256(i) S2B_128(i) S2B_128(i)
-static const uint8_t const_small_size2bin[PAGE_SIZE - 255] = {
- S2B_1(0xffU) /* 0 */
-#if (LG_QUANTUM == 4)
-/* 64-bit system ************************/
-# ifdef MALLOC_TINY
- S2B_2(0) /* 2 */
- S2B_2(1) /* 4 */
- S2B_4(2) /* 8 */
- S2B_8(3) /* 16 */
-# define S2B_QMIN 3
-# else
- S2B_16(0) /* 16 */
-# define S2B_QMIN 0
-# endif
- S2B_16(S2B_QMIN + 1) /* 32 */
- S2B_16(S2B_QMIN + 2) /* 48 */
- S2B_16(S2B_QMIN + 3) /* 64 */
- S2B_16(S2B_QMIN + 4) /* 80 */
- S2B_16(S2B_QMIN + 5) /* 96 */
- S2B_16(S2B_QMIN + 6) /* 112 */
- S2B_16(S2B_QMIN + 7) /* 128 */
-# define S2B_CMIN (S2B_QMIN + 8)
-#else
-/* 32-bit system ************************/
-# ifdef MALLOC_TINY
- S2B_2(0) /* 2 */
- S2B_2(1) /* 4 */
- S2B_4(2) /* 8 */
-# define S2B_QMIN 2
-# else
- S2B_8(0) /* 8 */
-# define S2B_QMIN 0
-# endif
- S2B_8(S2B_QMIN + 1) /* 16 */
- S2B_8(S2B_QMIN + 2) /* 24 */
- S2B_8(S2B_QMIN + 3) /* 32 */
- S2B_8(S2B_QMIN + 4) /* 40 */
- S2B_8(S2B_QMIN + 5) /* 48 */
- S2B_8(S2B_QMIN + 6) /* 56 */
- S2B_8(S2B_QMIN + 7) /* 64 */
- S2B_8(S2B_QMIN + 8) /* 72 */
- S2B_8(S2B_QMIN + 9) /* 80 */
- S2B_8(S2B_QMIN + 10) /* 88 */
- S2B_8(S2B_QMIN + 11) /* 96 */
- S2B_8(S2B_QMIN + 12) /* 104 */
- S2B_8(S2B_QMIN + 13) /* 112 */
- S2B_8(S2B_QMIN + 14) /* 120 */
- S2B_8(S2B_QMIN + 15) /* 128 */
-# define S2B_CMIN (S2B_QMIN + 16)
-#endif
-/****************************************/
- S2B_64(S2B_CMIN + 0) /* 192 */
- S2B_64(S2B_CMIN + 1) /* 256 */
- S2B_64(S2B_CMIN + 2) /* 320 */
- S2B_64(S2B_CMIN + 3) /* 384 */
- S2B_64(S2B_CMIN + 4) /* 448 */
- S2B_64(S2B_CMIN + 5) /* 512 */
-# define S2B_SMIN (S2B_CMIN + 6)
- S2B_256(S2B_SMIN + 0) /* 768 */
- S2B_256(S2B_SMIN + 1) /* 1024 */
- S2B_256(S2B_SMIN + 2) /* 1280 */
- S2B_256(S2B_SMIN + 3) /* 1536 */
- S2B_256(S2B_SMIN + 4) /* 1792 */
- S2B_256(S2B_SMIN + 5) /* 2048 */
- S2B_256(S2B_SMIN + 6) /* 2304 */
- S2B_256(S2B_SMIN + 7) /* 2560 */
- S2B_256(S2B_SMIN + 8) /* 2816 */
- S2B_256(S2B_SMIN + 9) /* 3072 */
- S2B_256(S2B_SMIN + 10) /* 3328 */
- S2B_256(S2B_SMIN + 11) /* 3584 */
- S2B_256(S2B_SMIN + 12) /* 3840 */
-#if (PAGE_SHIFT == 13)
- S2B_256(S2B_SMIN + 13) /* 4096 */
- S2B_256(S2B_SMIN + 14) /* 4352 */
- S2B_256(S2B_SMIN + 15) /* 4608 */
- S2B_256(S2B_SMIN + 16) /* 4864 */
- S2B_256(S2B_SMIN + 17) /* 5120 */
- S2B_256(S2B_SMIN + 18) /* 5376 */
- S2B_256(S2B_SMIN + 19) /* 5632 */
- S2B_256(S2B_SMIN + 20) /* 5888 */
- S2B_256(S2B_SMIN + 21) /* 6144 */
- S2B_256(S2B_SMIN + 22) /* 6400 */
- S2B_256(S2B_SMIN + 23) /* 6656 */
- S2B_256(S2B_SMIN + 24) /* 6912 */
- S2B_256(S2B_SMIN + 25) /* 7168 */
- S2B_256(S2B_SMIN + 26) /* 7424 */
- S2B_256(S2B_SMIN + 27) /* 7680 */
- S2B_256(S2B_SMIN + 28) /* 7936 */
-#endif
-};
-#undef S2B_1
-#undef S2B_2
-#undef S2B_4
-#undef S2B_8
-#undef S2B_16
-#undef S2B_32
-#undef S2B_64
-#undef S2B_128
-#undef S2B_256
-#undef S2B_QMIN
-#undef S2B_CMIN
-#undef S2B_SMIN
-
-/* Various chunk-related settings. */
-static size_t chunksize;
-static size_t chunksize_mask; /* (chunksize - 1). */
-static size_t chunk_npages;
-static size_t arena_chunk_header_npages;
-static size_t arena_maxclass; /* Max size class for arenas. */
-
-/********/
-/*
- * Chunks.
- */
-
-/* Protects chunk-related data structures. */
-static malloc_mutex_t huge_mtx;
-
-/* Tree of chunks that are stand-alone huge allocations. */
-static extent_tree_t huge;
-
-#ifdef MALLOC_DSS
-/*
- * Protects sbrk() calls. This avoids malloc races among threads, though it
- * does not protect against races with threads that call sbrk() directly.
- */
-static malloc_mutex_t dss_mtx;
-/* Base address of the DSS. */
-static void *dss_base;
-/* Current end of the DSS, or ((void *)-1) if the DSS is exhausted. */
-static void *dss_prev;
-/* Current upper limit on DSS addresses. */
-static void *dss_max;
-
-/*
- * Trees of chunks that were previously allocated (trees differ only in node
- * ordering). These are used when allocating chunks, in an attempt to re-use
- * address space. Depending on function, different tree orderings are needed,
- * which is why there are two trees with the same contents.
- */
-static extent_tree_t dss_chunks_szad;
-static extent_tree_t dss_chunks_ad;
-#endif
-
-#ifdef MALLOC_STATS
-/* Huge allocation statistics. */
-static uint64_t huge_nmalloc;
-static uint64_t huge_ndalloc;
-static size_t huge_allocated;
-#endif
-
-/****************************/
-/*
- * base (internal allocation).
- */
-
-/*
- * Current pages that are being used for internal memory allocations. These
- * pages are carved up in cacheline-size quanta, so that there is no chance of
- * false cache line sharing.
- */
-static void *base_pages;
-static void *base_next_addr;
-static void *base_past_addr; /* Addr immediately past base_pages. */
-static extent_node_t *base_nodes;
-static malloc_mutex_t base_mtx;
-#ifdef MALLOC_STATS
-static size_t base_mapped;
-#endif
-
-/********/
-/*
- * Arenas.
- */
-
-/*
- * Arenas that are used to service external requests. Not all elements of the
- * arenas array are necessarily used; arenas are created lazily as needed.
- */
-static arena_t **arenas;
-static unsigned narenas;
-#ifndef NO_TLS
-static unsigned next_arena;
-#endif
-static pthread_mutex_t arenas_lock; /* Protects arenas initialization. */
-
-#ifndef NO_TLS
-/*
- * Map of _pthread_self() --> arenas[???], used for selecting an arena to use
- * for allocations.
- */
-static __thread arena_t *arenas_map TLS_MODEL;
-#endif
-
-#ifdef MALLOC_TCACHE
-/* Map of thread-specific caches. */
-static __thread tcache_t *tcache_tls TLS_MODEL;
-
-/*
- * Number of cache slots for each bin in the thread cache, or 0 if tcache is
- * disabled.
- */
-size_t tcache_nslots;
-
-/* Number of tcache allocation/deallocation events between incremental GCs. */
-unsigned tcache_gc_incr;
-#endif
-
-/*
- * Used by chunk_alloc_mmap() to decide whether to attempt the fast path and
- * potentially avoid some system calls. We can get away without TLS here,
- * since the state of mmap_unaligned only affects performance, rather than
- * correct function.
- */
-#ifndef NO_TLS
-static __thread bool mmap_unaligned TLS_MODEL;
-#else
-static bool mmap_unaligned;
-#endif
-
-#ifdef MALLOC_STATS
-static malloc_mutex_t chunks_mtx;
-/* Chunk statistics. */
-static chunk_stats_t stats_chunks;
-#endif
-
-/*******************************/
-/*
- * Runtime configuration options.
- */
-const char *_malloc_options;
-
-#ifndef MALLOC_PRODUCTION
-static bool opt_abort = true;
-static bool opt_junk = true;
-#else
-static bool opt_abort = false;
-static bool opt_junk = false;
-#endif
-#ifdef MALLOC_TCACHE
-static size_t opt_lg_tcache_nslots = LG_TCACHE_NSLOTS_DEFAULT;
-static ssize_t opt_lg_tcache_gc_sweep = LG_TCACHE_GC_SWEEP_DEFAULT;
-#endif
-#ifdef MALLOC_DSS
-static bool opt_dss = true;
-static bool opt_mmap = true;
-#endif
-static ssize_t opt_lg_dirty_mult = LG_DIRTY_MULT_DEFAULT;
-static bool opt_stats_print = false;
-static size_t opt_lg_qspace_max = LG_QSPACE_MAX_DEFAULT;
-static size_t opt_lg_cspace_max = LG_CSPACE_MAX_DEFAULT;
-static size_t opt_lg_medium_max = LG_MEDIUM_MAX_DEFAULT;
-static size_t opt_lg_chunk = LG_CHUNK_DEFAULT;
-static bool opt_utrace = false;
-static bool opt_sysv = false;
-static bool opt_xmalloc = false;
-static bool opt_zero = false;
-static int opt_narenas_lshift = 0;
-
-typedef struct {
- void *p;
- size_t s;
- void *r;
-} malloc_utrace_t;
-
-#define UTRACE(a, b, c) \
- if (opt_utrace) { \
- malloc_utrace_t ut; \
- ut.p = (a); \
- ut.s = (b); \
- ut.r = (c); \
- utrace(&ut, sizeof(ut)); \
- }
-
-/******************************************************************************/
-/*
- * Begin function prototypes for non-inline static functions.
- */
-
-static void malloc_mutex_init(malloc_mutex_t *mutex);
-static bool malloc_spin_init(pthread_mutex_t *lock);
-#ifdef MALLOC_TINY
-static size_t pow2_ceil(size_t x);
-#endif
-static void wrtmessage(const char *p1, const char *p2, const char *p3,
- const char *p4);
-#ifdef MALLOC_STATS
-static void malloc_printf(const char *format, ...);
-#endif
-static char *umax2s(uintmax_t x, unsigned base, char *s);
-#ifdef MALLOC_DSS
-static bool base_pages_alloc_dss(size_t minsize);
-#endif
-static bool base_pages_alloc_mmap(size_t minsize);
-static bool base_pages_alloc(size_t minsize);
-static void *base_alloc(size_t size);
-static void *base_calloc(size_t number, size_t size);
-static extent_node_t *base_node_alloc(void);
-static void base_node_dealloc(extent_node_t *node);
-static void *pages_map(void *addr, size_t size);
-static void pages_unmap(void *addr, size_t size);
-#ifdef MALLOC_DSS
-static void *chunk_alloc_dss(size_t size, bool *zero);
-static void *chunk_recycle_dss(size_t size, bool *zero);
-#endif
-static void *chunk_alloc_mmap_slow(size_t size, bool unaligned);
-static void *chunk_alloc_mmap(size_t size);
-static void *chunk_alloc(size_t size, bool *zero);
-#ifdef MALLOC_DSS
-static extent_node_t *chunk_dealloc_dss_record(void *chunk, size_t size);
-static bool chunk_dealloc_dss(void *chunk, size_t size);
-#endif
-static void chunk_dealloc_mmap(void *chunk, size_t size);
-static void chunk_dealloc(void *chunk, size_t size);
-#ifndef NO_TLS
-static arena_t *choose_arena_hard(void);
-#endif
-static void arena_run_split(arena_t *arena, arena_run_t *run, size_t size,
- bool large, bool zero);
-static arena_chunk_t *arena_chunk_alloc(arena_t *arena);
-static void arena_chunk_dealloc(arena_t *arena, arena_chunk_t *chunk);
-static arena_run_t *arena_run_alloc(arena_t *arena, size_t size, bool large,
- bool zero);
-static void arena_purge(arena_t *arena);
-static void arena_run_dalloc(arena_t *arena, arena_run_t *run, bool dirty);
-static void arena_run_trim_head(arena_t *arena, arena_chunk_t *chunk,
- arena_run_t *run, size_t oldsize, size_t newsize);
-static void arena_run_trim_tail(arena_t *arena, arena_chunk_t *chunk,
- arena_run_t *run, size_t oldsize, size_t newsize, bool dirty);
-static arena_run_t *arena_bin_nonfull_run_get(arena_t *arena, arena_bin_t *bin);
-static void *arena_bin_malloc_hard(arena_t *arena, arena_bin_t *bin);
-static size_t arena_bin_run_size_calc(arena_bin_t *bin, size_t min_run_size);
-#ifdef MALLOC_TCACHE
-static void tcache_bin_fill(tcache_t *tcache, tcache_bin_t *tbin,
- size_t binind);
-static void *tcache_alloc_hard(tcache_t *tcache, tcache_bin_t *tbin,
- size_t binind);
-#endif
-static void *arena_malloc_medium(arena_t *arena, size_t size, bool zero);
-static void *arena_malloc_large(arena_t *arena, size_t size, bool zero);
-static void *arena_palloc(arena_t *arena, size_t alignment, size_t size,
- size_t alloc_size);
-static bool arena_is_large(const void *ptr);
-static size_t arena_salloc(const void *ptr);
-static void
-arena_dalloc_bin_run(arena_t *arena, arena_chunk_t *chunk, arena_run_t *run,
- arena_bin_t *bin);
-#ifdef MALLOC_STATS
-static void arena_stats_print(arena_t *arena);
-#endif
-static void stats_print_atexit(void);
-#ifdef MALLOC_TCACHE
-static void tcache_bin_flush(tcache_bin_t *tbin, size_t binind,
- unsigned rem);
-#endif
-static void arena_dalloc_large(arena_t *arena, arena_chunk_t *chunk,
- void *ptr);
-#ifdef MALLOC_TCACHE
-static void arena_dalloc_hard(arena_t *arena, arena_chunk_t *chunk,
- void *ptr, arena_chunk_map_t *mapelm, tcache_t *tcache);
-#endif
-static void arena_ralloc_large_shrink(arena_t *arena, arena_chunk_t *chunk,
- void *ptr, size_t size, size_t oldsize);
-static bool arena_ralloc_large_grow(arena_t *arena, arena_chunk_t *chunk,
- void *ptr, size_t size, size_t oldsize);
-static bool arena_ralloc_large(void *ptr, size_t size, size_t oldsize);
-static void *arena_ralloc(void *ptr, size_t size, size_t oldsize);
-static bool arena_new(arena_t *arena, unsigned ind);
-static arena_t *arenas_extend(unsigned ind);
-#ifdef MALLOC_TCACHE
-static tcache_bin_t *tcache_bin_create(arena_t *arena);
-static void tcache_bin_destroy(tcache_t *tcache, tcache_bin_t *tbin,
- unsigned binind);
-# ifdef MALLOC_STATS
-static void tcache_stats_merge(tcache_t *tcache, arena_t *arena);
-# endif
-static tcache_t *tcache_create(arena_t *arena);
-static void tcache_destroy(tcache_t *tcache);
-#endif
-static void *huge_malloc(size_t size, bool zero);
-static void *huge_palloc(size_t alignment, size_t size);
-static void *huge_ralloc(void *ptr, size_t size, size_t oldsize);
-static void huge_dalloc(void *ptr);
-static void malloc_stats_print(void);
-#ifdef MALLOC_DEBUG
-static void small_size2bin_validate(void);
-#endif
-static bool small_size2bin_init(void);
-static bool small_size2bin_init_hard(void);
-static unsigned malloc_ncpus(void);
-static bool malloc_init_hard(void);
-
-/*
- * End function prototypes.
- */
-/******************************************************************************/
-
-static void
-wrtmessage(const char *p1, const char *p2, const char *p3, const char *p4)
-{
-
- if (_write(STDERR_FILENO, p1, strlen(p1)) < 0
- || _write(STDERR_FILENO, p2, strlen(p2)) < 0
- || _write(STDERR_FILENO, p3, strlen(p3)) < 0
- || _write(STDERR_FILENO, p4, strlen(p4)) < 0)
- return;
-}
-
-void (*_malloc_message)(const char *p1, const char *p2, const char *p3,
- const char *p4) = wrtmessage;
-
-/*
- * We don't want to depend on vsnprintf() for production builds, since that can
- * cause unnecessary bloat for static binaries. umax2s() provides minimal
- * integer printing functionality, so that malloc_printf() use can be limited to
- * MALLOC_STATS code.
- */
-#define UMAX2S_BUFSIZE 65
-static char *
-umax2s(uintmax_t x, unsigned base, char *s)
-{
- unsigned i;
-
- i = UMAX2S_BUFSIZE - 1;
- s[i] = '\0';
- switch (base) {
- case 10:
- do {
- i--;
- s[i] = "0123456789"[x % 10];
- x /= 10;
- } while (x > 0);
- break;
- case 16:
- do {
- i--;
- s[i] = "0123456789abcdef"[x & 0xf];
- x >>= 4;
- } while (x > 0);
- break;
- default:
- do {
- i--;
- s[i] = "0123456789abcdefghijklmnopqrstuvwxyz"[x % base];
- x /= base;
- } while (x > 0);
- }
-
- return (&s[i]);
-}
-
-/*
- * Define a custom assert() in order to reduce the chances of deadlock during
- * assertion failure.
- */
-#ifdef MALLOC_DEBUG
-# define assert(e) do { \
- if (!(e)) { \
- char line_buf[UMAX2S_BUFSIZE]; \
- _malloc_message(_getprogname(), ": (malloc) ", \
- __FILE__, ":"); \
- _malloc_message(umax2s(__LINE__, 10, line_buf), \
- ": Failed assertion: ", "\"", #e); \
- _malloc_message("\"\n", "", "", ""); \
- abort(); \
- } \
-} while (0)
-#else
-#define assert(e)
-#endif
-
-#ifdef MALLOC_STATS
-/*
- * Print to stderr in such a way as to (hopefully) avoid memory allocation.
- */
-static void
-malloc_printf(const char *format, ...)
-{
- char buf[4096];
- va_list ap;
-
- va_start(ap, format);
- vsnprintf(buf, sizeof(buf), format, ap);
- va_end(ap);
- _malloc_message(buf, "", "", "");
-}
-#endif
-
-/******************************************************************************/
-/*
- * Begin mutex. We can't use normal pthread mutexes in all places, because
- * they require malloc()ed memory, which causes bootstrapping issues in some
- * cases.
- */
-
-static void
-malloc_mutex_init(malloc_mutex_t *mutex)
-{
- static const spinlock_t lock = _SPINLOCK_INITIALIZER;
-
- mutex->lock = lock;
-}
-
-static inline void
-malloc_mutex_lock(malloc_mutex_t *mutex)
-{
-
- if (__isthreaded)
- _SPINLOCK(&mutex->lock);
-}
-
-static inline void
-malloc_mutex_unlock(malloc_mutex_t *mutex)
-{
-
- if (__isthreaded)
- _SPINUNLOCK(&mutex->lock);
-}
-
-/*
- * End mutex.
- */
-/******************************************************************************/
-/*
- * Begin spin lock. Spin locks here are actually adaptive mutexes that block
- * after a period of spinning, because unbounded spinning would allow for
- * priority inversion.
- */
-
-/*
- * We use an unpublished interface to initialize pthread mutexes with an
- * allocation callback, in order to avoid infinite recursion.
- */
-int _pthread_mutex_init_calloc_cb(pthread_mutex_t *mutex,
- void *(calloc_cb)(size_t, size_t));
-
-__weak_reference(_pthread_mutex_init_calloc_cb_stub,
- _pthread_mutex_init_calloc_cb);
-
-int
-_pthread_mutex_init_calloc_cb_stub(pthread_mutex_t *mutex,
- void *(calloc_cb)(size_t, size_t))
-{
-
- return (0);
-}
-
-static bool
-malloc_spin_init(pthread_mutex_t *lock)
-{
-
- if (_pthread_mutex_init_calloc_cb(lock, base_calloc) != 0)
- return (true);
-
- return (false);
-}
-
-static inline void
-malloc_spin_lock(pthread_mutex_t *lock)
-{
-
- if (__isthreaded) {
- if (_pthread_mutex_trylock(lock) != 0) {
- /* Exponentially back off if there are multiple CPUs. */
- if (ncpus > 1) {
- unsigned i;
- volatile unsigned j;
-
- for (i = 1; i <= LG_SPIN_LIMIT; i++) {
- for (j = 0; j < (1U << i); j++) {
- CPU_SPINWAIT;
- }
-
- if (_pthread_mutex_trylock(lock) == 0)
- return;
- }
- }
-
- /*
- * Spinning failed. Block until the lock becomes
- * available, in order to avoid indefinite priority
- * inversion.
- */
- _pthread_mutex_lock(lock);
- }
- }
-}
-
-static inline void
-malloc_spin_unlock(pthread_mutex_t *lock)
-{
-
- if (__isthreaded)
- _pthread_mutex_unlock(lock);
-}
-
-/*
- * End spin lock.
- */
-/******************************************************************************/
-/*
- * Begin Utility functions/macros.
- */
-
-/* Return the chunk address for allocation address a. */
-#define CHUNK_ADDR2BASE(a) \
- ((void *)((uintptr_t)(a) & ~chunksize_mask))
-
-/* Return the chunk offset of address a. */
-#define CHUNK_ADDR2OFFSET(a) \
- ((size_t)((uintptr_t)(a) & chunksize_mask))
-
-/* Return the smallest chunk multiple that is >= s. */
-#define CHUNK_CEILING(s) \
- (((s) + chunksize_mask) & ~chunksize_mask)
-
-/* Return the smallest quantum multiple that is >= a. */
-#define QUANTUM_CEILING(a) \
- (((a) + QUANTUM_MASK) & ~QUANTUM_MASK)
-
-/* Return the smallest cacheline multiple that is >= s. */
-#define CACHELINE_CEILING(s) \
- (((s) + CACHELINE_MASK) & ~CACHELINE_MASK)
-
-/* Return the smallest subpage multiple that is >= s. */
-#define SUBPAGE_CEILING(s) \
- (((s) + SUBPAGE_MASK) & ~SUBPAGE_MASK)
-
-/* Return the smallest medium size class that is >= s. */
-#define MEDIUM_CEILING(s) \
- (((s) + mspace_mask) & ~mspace_mask)
-
-/* Return the smallest pagesize multiple that is >= s. */
-#define PAGE_CEILING(s) \
- (((s) + PAGE_MASK) & ~PAGE_MASK)
-
-#ifdef MALLOC_TINY
-/* Compute the smallest power of 2 that is >= x. */
-static size_t
-pow2_ceil(size_t x)
-{
-
- x--;
- x |= x >> 1;
- x |= x >> 2;
- x |= x >> 4;
- x |= x >> 8;
- x |= x >> 16;
-#if (SIZEOF_PTR == 8)
- x |= x >> 32;
-#endif
- x++;
- return (x);
-}
-#endif
-
-/******************************************************************************/
-
-#ifdef MALLOC_DSS
-static bool
-base_pages_alloc_dss(size_t minsize)
-{
-
- /*
- * Do special DSS allocation here, since base allocations don't need to
- * be chunk-aligned.
- */
- malloc_mutex_lock(&dss_mtx);
- if (dss_prev != (void *)-1) {
- intptr_t incr;
- size_t csize = CHUNK_CEILING(minsize);
-
- do {
- /* Get the current end of the DSS. */
- dss_max = sbrk(0);
-
- /*
- * Calculate how much padding is necessary to
- * chunk-align the end of the DSS. Don't worry about
- * dss_max not being chunk-aligned though.
- */
- incr = (intptr_t)chunksize
- - (intptr_t)CHUNK_ADDR2OFFSET(dss_max);
- assert(incr >= 0);
- if ((size_t)incr < minsize)
- incr += csize;
-
- dss_prev = sbrk(incr);
- if (dss_prev == dss_max) {
- /* Success. */
- dss_max = (void *)((intptr_t)dss_prev + incr);
- base_pages = dss_prev;
- base_next_addr = base_pages;
- base_past_addr = dss_max;
-#ifdef MALLOC_STATS
- base_mapped += incr;
-#endif
- malloc_mutex_unlock(&dss_mtx);
- return (false);
- }
- } while (dss_prev != (void *)-1);
- }
- malloc_mutex_unlock(&dss_mtx);
-
- return (true);
-}
-#endif
-
-static bool
-base_pages_alloc_mmap(size_t minsize)
-{
- size_t csize;
-
- assert(minsize != 0);
- csize = PAGE_CEILING(minsize);
- base_pages = pages_map(NULL, csize);
- if (base_pages == NULL)
- return (true);
- base_next_addr = base_pages;
- base_past_addr = (void *)((uintptr_t)base_pages + csize);
-#ifdef MALLOC_STATS
- base_mapped += csize;
-#endif
-
- return (false);
-}
-
-static bool
-base_pages_alloc(size_t minsize)
-{
-
-#ifdef MALLOC_DSS
- if (opt_mmap && minsize != 0)
-#endif
- {
- if (base_pages_alloc_mmap(minsize) == false)
- return (false);
- }
-
-#ifdef MALLOC_DSS
- if (opt_dss) {
- if (base_pages_alloc_dss(minsize) == false)
- return (false);
- }
-
-#endif
-
- return (true);
-}
-
-static void *
-base_alloc(size_t size)
-{
- void *ret;
- size_t csize;
-
- /* Round size up to nearest multiple of the cacheline size. */
- csize = CACHELINE_CEILING(size);
-
- malloc_mutex_lock(&base_mtx);
- /* Make sure there's enough space for the allocation. */
- if ((uintptr_t)base_next_addr + csize > (uintptr_t)base_past_addr) {
- if (base_pages_alloc(csize)) {
- malloc_mutex_unlock(&base_mtx);
- return (NULL);
- }
- }
- /* Allocate. */
- ret = base_next_addr;
- base_next_addr = (void *)((uintptr_t)base_next_addr + csize);
- malloc_mutex_unlock(&base_mtx);
-
- return (ret);
-}
-
-static void *
-base_calloc(size_t number, size_t size)
-{
- void *ret;
-
- ret = base_alloc(number * size);
- if (ret != NULL)
- memset(ret, 0, number * size);
-
- return (ret);
-}
-
-static extent_node_t *
-base_node_alloc(void)
-{
- extent_node_t *ret;
-
- malloc_mutex_lock(&base_mtx);
- if (base_nodes != NULL) {
- ret = base_nodes;
- base_nodes = *(extent_node_t **)ret;
- malloc_mutex_unlock(&base_mtx);
- } else {
- malloc_mutex_unlock(&base_mtx);
- ret = (extent_node_t *)base_alloc(sizeof(extent_node_t));
- }
-
- return (ret);
-}
-
-static void
-base_node_dealloc(extent_node_t *node)
-{
-
- malloc_mutex_lock(&base_mtx);
- *(extent_node_t **)node = base_nodes;
- base_nodes = node;
- malloc_mutex_unlock(&base_mtx);
-}
-
-/*
- * End Utility functions/macros.
- */
-/******************************************************************************/
-/*
- * Begin extent tree code.
- */
-
-#ifdef MALLOC_DSS
-static inline int
-extent_szad_comp(extent_node_t *a, extent_node_t *b)
-{
- int ret;
- size_t a_size = a->size;
- size_t b_size = b->size;
-
- ret = (a_size > b_size) - (a_size < b_size);
- if (ret == 0) {
- uintptr_t a_addr = (uintptr_t)a->addr;
- uintptr_t b_addr = (uintptr_t)b->addr;
-
- ret = (a_addr > b_addr) - (a_addr < b_addr);
- }
-
- return (ret);
-}
-
-/* Wrap red-black tree macros in functions. */
-rb_gen(__unused static, extent_tree_szad_, extent_tree_t, extent_node_t,
- link_szad, extent_szad_comp)
-#endif
-
-static inline int
-extent_ad_comp(extent_node_t *a, extent_node_t *b)
-{
- uintptr_t a_addr = (uintptr_t)a->addr;
- uintptr_t b_addr = (uintptr_t)b->addr;
-
- return ((a_addr > b_addr) - (a_addr < b_addr));
-}
-
-/* Wrap red-black tree macros in functions. */
-rb_gen(__unused static, extent_tree_ad_, extent_tree_t, extent_node_t, link_ad,
- extent_ad_comp)
-
-/*
- * End extent tree code.
- */
-/******************************************************************************/
-/*
- * Begin chunk management functions.
- */
-
-static void *
-pages_map(void *addr, size_t size)
-{
- void *ret;
-
- /*
- * We don't use MAP_FIXED here, because it can cause the *replacement*
- * of existing mappings, and we only want to create new mappings.
- */
- ret = mmap(addr, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON,
- -1, 0);
- assert(ret != NULL);
-
- if (ret == MAP_FAILED)
- ret = NULL;
- else if (addr != NULL && ret != addr) {
- /*
- * We succeeded in mapping memory, but not in the right place.
- */
- if (munmap(ret, size) == -1) {
- char buf[STRERROR_BUF];
-
- strerror_r(errno, buf, sizeof(buf));
- _malloc_message(_getprogname(),
- ": (malloc) Error in munmap(): ", buf, "\n");
- if (opt_abort)
- abort();
- }
- ret = NULL;
- }
-
- assert(ret == NULL || (addr == NULL && ret != addr)
- || (addr != NULL && ret == addr));
- return (ret);
-}
-
-static void
-pages_unmap(void *addr, size_t size)
-{
-
- if (munmap(addr, size) == -1) {
- char buf[STRERROR_BUF];
-
- strerror_r(errno, buf, sizeof(buf));
- _malloc_message(_getprogname(),
- ": (malloc) Error in munmap(): ", buf, "\n");
- if (opt_abort)
- abort();
- }
-}
-
-#ifdef MALLOC_DSS
-static void *
-chunk_alloc_dss(size_t size, bool *zero)
-{
- void *ret;
-
- ret = chunk_recycle_dss(size, zero);
- if (ret != NULL)
- return (ret);
-
- /*
- * sbrk() uses a signed increment argument, so take care not to
- * interpret a huge allocation request as a negative increment.
- */
- if ((intptr_t)size < 0)
- return (NULL);
-
- malloc_mutex_lock(&dss_mtx);
- if (dss_prev != (void *)-1) {
- intptr_t incr;
-
- /*
- * The loop is necessary to recover from races with other
- * threads that are using the DSS for something other than
- * malloc.
- */
- do {
- /* Get the current end of the DSS. */
- dss_max = sbrk(0);
-
- /*
- * Calculate how much padding is necessary to
- * chunk-align the end of the DSS.
- */
- incr = (intptr_t)size
- - (intptr_t)CHUNK_ADDR2OFFSET(dss_max);
- if (incr == (intptr_t)size)
- ret = dss_max;
- else {
- ret = (void *)((intptr_t)dss_max + incr);
- incr += size;
- }
-
- dss_prev = sbrk(incr);
- if (dss_prev == dss_max) {
- /* Success. */
- dss_max = (void *)((intptr_t)dss_prev + incr);
- malloc_mutex_unlock(&dss_mtx);
- *zero = true;
- return (ret);
- }
- } while (dss_prev != (void *)-1);
- }
- malloc_mutex_unlock(&dss_mtx);
-
- return (NULL);
-}
-
-static void *
-chunk_recycle_dss(size_t size, bool *zero)
-{
- extent_node_t *node, key;
-
- key.addr = NULL;
- key.size = size;
- malloc_mutex_lock(&dss_mtx);
- node = extent_tree_szad_nsearch(&dss_chunks_szad, &key);
- if (node != NULL) {
- void *ret = node->addr;
-
- /* Remove node from the tree. */
- extent_tree_szad_remove(&dss_chunks_szad, node);
- if (node->size == size) {
- extent_tree_ad_remove(&dss_chunks_ad, node);
- base_node_dealloc(node);
- } else {
- /*
- * Insert the remainder of node's address range as a
- * smaller chunk. Its position within dss_chunks_ad
- * does not change.
- */
- assert(node->size > size);
- node->addr = (void *)((uintptr_t)node->addr + size);
- node->size -= size;
- extent_tree_szad_insert(&dss_chunks_szad, node);
- }
- malloc_mutex_unlock(&dss_mtx);
-
- if (*zero)
- memset(ret, 0, size);
- return (ret);
- }
- malloc_mutex_unlock(&dss_mtx);
-
- return (NULL);
-}
-#endif
-
-static void *
-chunk_alloc_mmap_slow(size_t size, bool unaligned)
-{
- void *ret;
- size_t offset;
-
- /* Beware size_t wrap-around. */
- if (size + chunksize <= size)
- return (NULL);
-
- ret = pages_map(NULL, size + chunksize);
- if (ret == NULL)
- return (NULL);
-
- /* Clean up unneeded leading/trailing space. */
- offset = CHUNK_ADDR2OFFSET(ret);
- if (offset != 0) {
- /* Note that mmap() returned an unaligned mapping. */
- unaligned = true;
-
- /* Leading space. */
- pages_unmap(ret, chunksize - offset);
-
- ret = (void *)((uintptr_t)ret +
- (chunksize - offset));
-
- /* Trailing space. */
- pages_unmap((void *)((uintptr_t)ret + size),
- offset);
- } else {
- /* Trailing space only. */
- pages_unmap((void *)((uintptr_t)ret + size),
- chunksize);
- }
-
- /*
- * If mmap() returned an aligned mapping, reset mmap_unaligned so that
- * the next chunk_alloc_mmap() execution tries the fast allocation
- * method.
- */
- if (unaligned == false)
- mmap_unaligned = false;
-
- return (ret);
-}
-
-static void *
-chunk_alloc_mmap(size_t size)
-{
- void *ret;
-
- /*
- * Ideally, there would be a way to specify alignment to mmap() (like
- * NetBSD has), but in the absence of such a feature, we have to work
- * hard to efficiently create aligned mappings. The reliable, but
- * slow method is to create a mapping that is over-sized, then trim the
- * excess. However, that always results in at least one call to
- * pages_unmap().
- *
- * A more optimistic approach is to try mapping precisely the right
- * amount, then try to append another mapping if alignment is off. In
- * practice, this works out well as long as the application is not
- * interleaving mappings via direct mmap() calls. If we do run into a
- * situation where there is an interleaved mapping and we are unable to
- * extend an unaligned mapping, our best option is to switch to the
- * slow method until mmap() returns another aligned mapping. This will
- * tend to leave a gap in the memory map that is too small to cause
- * later problems for the optimistic method.
- *
- * Another possible confounding factor is address space layout
- * randomization (ASLR), which causes mmap(2) to disregard the
- * requested address. mmap_unaligned tracks whether the previous
- * chunk_alloc_mmap() execution received any unaligned or relocated
- * mappings, and if so, the current execution will immediately fall
- * back to the slow method. However, we keep track of whether the fast
- * method would have succeeded, and if so, we make a note to try the
- * fast method next time.
- */
-
- if (mmap_unaligned == false) {
- size_t offset;
-
- ret = pages_map(NULL, size);
- if (ret == NULL)
- return (NULL);
-
- offset = CHUNK_ADDR2OFFSET(ret);
- if (offset != 0) {
- mmap_unaligned = true;
- /* Try to extend chunk boundary. */
- if (pages_map((void *)((uintptr_t)ret + size),
- chunksize - offset) == NULL) {
- /*
- * Extension failed. Clean up, then revert to
- * the reliable-but-expensive method.
- */
- pages_unmap(ret, size);
- ret = chunk_alloc_mmap_slow(size, true);
- } else {
- /* Clean up unneeded leading space. */
- pages_unmap(ret, chunksize - offset);
- ret = (void *)((uintptr_t)ret + (chunksize -
- offset));
- }
- }
- } else
- ret = chunk_alloc_mmap_slow(size, false);
-
- return (ret);
-}
-
-/*
- * If the caller specifies (*zero == false), it is still possible to receive
- * zeroed memory, in which case *zero is toggled to true. arena_chunk_alloc()
- * takes advantage of this to avoid demanding zeroed chunks, but taking
- * advantage of them if they are returned.
- */
-static void *
-chunk_alloc(size_t size, bool *zero)
-{
- void *ret;
-
- assert(size != 0);
- assert((size & chunksize_mask) == 0);
-
-#ifdef MALLOC_DSS
- if (opt_mmap)
-#endif
- {
- ret = chunk_alloc_mmap(size);
- if (ret != NULL) {
- *zero = true;
- goto RETURN;
- }
- }
-
-#ifdef MALLOC_DSS
- if (opt_dss) {
- ret = chunk_alloc_dss(size, zero);
- if (ret != NULL)
- goto RETURN;
- }
-#endif
-
- /* All strategies for allocation failed. */
- ret = NULL;
-RETURN:
-#ifdef MALLOC_STATS
- if (ret != NULL) {
- malloc_mutex_lock(&chunks_mtx);
- stats_chunks.nchunks += (size / chunksize);
- stats_chunks.curchunks += (size / chunksize);
- if (stats_chunks.curchunks > stats_chunks.highchunks)
- stats_chunks.highchunks = stats_chunks.curchunks;
- malloc_mutex_unlock(&chunks_mtx);
- }
-#endif
-
- assert(CHUNK_ADDR2BASE(ret) == ret);
- return (ret);
-}
-
-#ifdef MALLOC_DSS
-static extent_node_t *
-chunk_dealloc_dss_record(void *chunk, size_t size)
-{
- extent_node_t *node, *prev, key;
-
- key.addr = (void *)((uintptr_t)chunk + size);
- node = extent_tree_ad_nsearch(&dss_chunks_ad, &key);
- /* Try to coalesce forward. */
- if (node != NULL && node->addr == key.addr) {
- /*
- * Coalesce chunk with the following address range. This does
- * not change the position within dss_chunks_ad, so only
- * remove/insert from/into dss_chunks_szad.
- */
- extent_tree_szad_remove(&dss_chunks_szad, node);
- node->addr = chunk;
- node->size += size;
- extent_tree_szad_insert(&dss_chunks_szad, node);
- } else {
- /*
- * Coalescing forward failed, so insert a new node. Drop
- * dss_mtx during node allocation, since it is possible that a
- * new base chunk will be allocated.
- */
- malloc_mutex_unlock(&dss_mtx);
- node = base_node_alloc();
- malloc_mutex_lock(&dss_mtx);
- if (node == NULL)
- return (NULL);
- node->addr = chunk;
- node->size = size;
- extent_tree_ad_insert(&dss_chunks_ad, node);
- extent_tree_szad_insert(&dss_chunks_szad, node);
- }
-
- /* Try to coalesce backward. */
- prev = extent_tree_ad_prev(&dss_chunks_ad, node);
- if (prev != NULL && (void *)((uintptr_t)prev->addr + prev->size) ==
- chunk) {
- /*
- * Coalesce chunk with the previous address range. This does
- * not change the position within dss_chunks_ad, so only
- * remove/insert node from/into dss_chunks_szad.
- */
- extent_tree_szad_remove(&dss_chunks_szad, prev);
- extent_tree_ad_remove(&dss_chunks_ad, prev);
-
- extent_tree_szad_remove(&dss_chunks_szad, node);
- node->addr = prev->addr;
- node->size += prev->size;
- extent_tree_szad_insert(&dss_chunks_szad, node);
-
- base_node_dealloc(prev);
- }
-
- return (node);
-}
-
-static bool
-chunk_dealloc_dss(void *chunk, size_t size)
-{
- bool ret;
-
- malloc_mutex_lock(&dss_mtx);
- if ((uintptr_t)chunk >= (uintptr_t)dss_base
- && (uintptr_t)chunk < (uintptr_t)dss_max) {
- extent_node_t *node;
-
- /* Try to coalesce with other unused chunks. */
- node = chunk_dealloc_dss_record(chunk, size);
- if (node != NULL) {
- chunk = node->addr;
- size = node->size;
- }
-
- /* Get the current end of the DSS. */
- dss_max = sbrk(0);
-
- /*
- * Try to shrink the DSS if this chunk is at the end of the
- * DSS. The sbrk() call here is subject to a race condition
- * with threads that use brk(2) or sbrk(2) directly, but the
- * alternative would be to leak memory for the sake of poorly
- * designed multi-threaded programs.
- */
- if ((void *)((uintptr_t)chunk + size) == dss_max
- && (dss_prev = sbrk(-(intptr_t)size)) == dss_max) {
- /* Success. */
- dss_max = (void *)((intptr_t)dss_prev - (intptr_t)size);
-
- if (node != NULL) {
- extent_tree_szad_remove(&dss_chunks_szad, node);
- extent_tree_ad_remove(&dss_chunks_ad, node);
- base_node_dealloc(node);
- }
- } else
- madvise(chunk, size, MADV_FREE);
-
- ret = false;
- goto RETURN;
- }
-
- ret = true;
-RETURN:
- malloc_mutex_unlock(&dss_mtx);
- return (ret);
-}
-#endif
-
-static void
-chunk_dealloc_mmap(void *chunk, size_t size)
-{
-
- pages_unmap(chunk, size);
-}
-
-static void
-chunk_dealloc(void *chunk, size_t size)
-{
-
- assert(chunk != NULL);
- assert(CHUNK_ADDR2BASE(chunk) == chunk);
- assert(size != 0);
- assert((size & chunksize_mask) == 0);
-
-#ifdef MALLOC_STATS
- malloc_mutex_lock(&chunks_mtx);
- stats_chunks.curchunks -= (size / chunksize);
- malloc_mutex_unlock(&chunks_mtx);
-#endif
-
-#ifdef MALLOC_DSS
- if (opt_dss) {
- if (chunk_dealloc_dss(chunk, size) == false)
- return;
- }
-
- if (opt_mmap)
-#endif
- chunk_dealloc_mmap(chunk, size);
-}
-
-/*
- * End chunk management functions.
- */
-/******************************************************************************/
-/*
- * Begin arena.
- */
-
-/*
- * Choose an arena based on a per-thread value (fast-path code, calls slow-path
- * code if necessary).
- */
-static inline arena_t *
-choose_arena(void)
-{
- arena_t *ret;
-
- /*
- * We can only use TLS if this is a PIC library, since for the static
- * library version, libc's malloc is used by TLS allocation, which
- * introduces a bootstrapping issue.
- */
-#ifndef NO_TLS
- if (__isthreaded == false) {
- /* Avoid the overhead of TLS for single-threaded operation. */
- return (arenas[0]);
- }
-
- ret = arenas_map;
- if (ret == NULL) {
- ret = choose_arena_hard();
- assert(ret != NULL);
- }
-#else
- if (__isthreaded && narenas > 1) {
- unsigned long ind;
-
- /*
- * Hash _pthread_self() to one of the arenas. There is a prime
- * number of arenas, so this has a reasonable chance of
- * working. Even so, the hashing can be easily thwarted by
- * inconvenient _pthread_self() values. Without specific
- * knowledge of how _pthread_self() calculates values, we can't
- * easily do much better than this.
- */
- ind = (unsigned long) _pthread_self() % narenas;
-
- /*
- * Optimistially assume that arenas[ind] has been initialized.
- * At worst, we find out that some other thread has already
- * done so, after acquiring the lock in preparation. Note that
- * this lazy locking also has the effect of lazily forcing
- * cache coherency; without the lock acquisition, there's no
- * guarantee that modification of arenas[ind] by another thread
- * would be seen on this CPU for an arbitrary amount of time.
- *
- * In general, this approach to modifying a synchronized value
- * isn't a good idea, but in this case we only ever modify the
- * value once, so things work out well.
- */
- ret = arenas[ind];
- if (ret == NULL) {
- /*
- * Avoid races with another thread that may have already
- * initialized arenas[ind].
- */
- malloc_spin_lock(&arenas_lock);
- if (arenas[ind] == NULL)
- ret = arenas_extend((unsigned)ind);
- else
- ret = arenas[ind];
- malloc_spin_unlock(&arenas_lock);
- }
- } else
- ret = arenas[0];
-#endif
-
- assert(ret != NULL);
- return (ret);
-}
-
-#ifndef NO_TLS
-/*
- * Choose an arena based on a per-thread value (slow-path code only, called
- * only by choose_arena()).
- */
-static arena_t *
-choose_arena_hard(void)
-{
- arena_t *ret;
-
- assert(__isthreaded);
-
- if (narenas > 1) {
- malloc_spin_lock(&arenas_lock);
- if ((ret = arenas[next_arena]) == NULL)
- ret = arenas_extend(next_arena);
- next_arena = (next_arena + 1) % narenas;
- malloc_spin_unlock(&arenas_lock);
- } else
- ret = arenas[0];
-
- arenas_map = ret;
-
- return (ret);
-}
-#endif
-
-static inline int
-arena_chunk_comp(arena_chunk_t *a, arena_chunk_t *b)
-{
- uintptr_t a_chunk = (uintptr_t)a;
- uintptr_t b_chunk = (uintptr_t)b;
-
- assert(a != NULL);
- assert(b != NULL);
-
- return ((a_chunk > b_chunk) - (a_chunk < b_chunk));
-}
-
-/* Wrap red-black tree macros in functions. */
-rb_gen(__unused static, arena_chunk_tree_dirty_, arena_chunk_tree_t,
- arena_chunk_t, link_dirty, arena_chunk_comp)
-
-static inline int
-arena_run_comp(arena_chunk_map_t *a, arena_chunk_map_t *b)
-{
- uintptr_t a_mapelm = (uintptr_t)a;
- uintptr_t b_mapelm = (uintptr_t)b;
-
- assert(a != NULL);
- assert(b != NULL);
-
- return ((a_mapelm > b_mapelm) - (a_mapelm < b_mapelm));
-}
-
-/* Wrap red-black tree macros in functions. */
-rb_gen(__unused static, arena_run_tree_, arena_run_tree_t, arena_chunk_map_t,
- link, arena_run_comp)
-
-static inline int
-arena_avail_comp(arena_chunk_map_t *a, arena_chunk_map_t *b)
-{
- int ret;
- size_t a_size = a->bits & ~PAGE_MASK;
- size_t b_size = b->bits & ~PAGE_MASK;
-
- ret = (a_size > b_size) - (a_size < b_size);
- if (ret == 0) {
- uintptr_t a_mapelm, b_mapelm;
-
- if ((a->bits & CHUNK_MAP_KEY) != CHUNK_MAP_KEY)
- a_mapelm = (uintptr_t)a;
- else {
- /*
- * Treat keys as though they are lower than anything
- * else.
- */
- a_mapelm = 0;
- }
- b_mapelm = (uintptr_t)b;
-
- ret = (a_mapelm > b_mapelm) - (a_mapelm < b_mapelm);
- }
-
- return (ret);
-}
-
-/* Wrap red-black tree macros in functions. */
-rb_gen(__unused static, arena_avail_tree_, arena_avail_tree_t,
- arena_chunk_map_t, link, arena_avail_comp)
-
-static inline void
-arena_run_rc_incr(arena_run_t *run, arena_bin_t *bin, const void *ptr)
-{
- arena_chunk_t *chunk;
- arena_t *arena;
- size_t pagebeg, pageend, i;
-
- chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);
- arena = chunk->arena;
- pagebeg = ((uintptr_t)ptr - (uintptr_t)chunk) >> PAGE_SHIFT;
- pageend = ((uintptr_t)ptr + (uintptr_t)(bin->reg_size - 1) -
- (uintptr_t)chunk) >> PAGE_SHIFT;
-
- for (i = pagebeg; i <= pageend; i++) {
- size_t mapbits = chunk->map[i].bits;
-
- if (mapbits & CHUNK_MAP_DIRTY) {
- assert((mapbits & CHUNK_MAP_RC_MASK) == 0);
- chunk->ndirty--;
- arena->ndirty--;
- mapbits ^= CHUNK_MAP_DIRTY;
- }
- assert((mapbits & CHUNK_MAP_RC_MASK) != CHUNK_MAP_RC_MASK);
- mapbits += CHUNK_MAP_RC_ONE;
- chunk->map[i].bits = mapbits;
- }
-}
-
-static inline void
-arena_run_rc_decr(arena_run_t *run, arena_bin_t *bin, const void *ptr)
-{
- arena_chunk_t *chunk;
- arena_t *arena;
- size_t pagebeg, pageend, mapbits, i;
- bool dirtier = false;
-
- chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);
- arena = chunk->arena;
- pagebeg = ((uintptr_t)ptr - (uintptr_t)chunk) >> PAGE_SHIFT;
- pageend = ((uintptr_t)ptr + (uintptr_t)(bin->reg_size - 1) -
- (uintptr_t)chunk) >> PAGE_SHIFT;
-
- /* First page. */
- mapbits = chunk->map[pagebeg].bits;
- mapbits -= CHUNK_MAP_RC_ONE;
- if ((mapbits & CHUNK_MAP_RC_MASK) == 0) {
- dirtier = true;
- assert((mapbits & CHUNK_MAP_DIRTY) == 0);
- mapbits |= CHUNK_MAP_DIRTY;
- chunk->ndirty++;
- arena->ndirty++;
- }
- chunk->map[pagebeg].bits = mapbits;
-
- if (pageend - pagebeg >= 1) {
- /*
- * Interior pages are completely consumed by the object being
- * deallocated, which means that the pages can be
- * unconditionally marked dirty.
- */
- for (i = pagebeg + 1; i < pageend; i++) {
- mapbits = chunk->map[i].bits;
- mapbits -= CHUNK_MAP_RC_ONE;
- assert((mapbits & CHUNK_MAP_RC_MASK) == 0);
- dirtier = true;
- assert((mapbits & CHUNK_MAP_DIRTY) == 0);
- mapbits |= CHUNK_MAP_DIRTY;
- chunk->ndirty++;
- arena->ndirty++;
- chunk->map[i].bits = mapbits;
- }
-
- /* Last page. */
- mapbits = chunk->map[pageend].bits;
- mapbits -= CHUNK_MAP_RC_ONE;
- if ((mapbits & CHUNK_MAP_RC_MASK) == 0) {
- dirtier = true;
- assert((mapbits & CHUNK_MAP_DIRTY) == 0);
- mapbits |= CHUNK_MAP_DIRTY;
- chunk->ndirty++;
- arena->ndirty++;
- }
- chunk->map[pageend].bits = mapbits;
- }
-
- if (dirtier) {
- if (chunk->dirtied == false) {
- arena_chunk_tree_dirty_insert(&arena->chunks_dirty,
- chunk);
- chunk->dirtied = true;
- }
-
- /* Enforce opt_lg_dirty_mult. */
- if (opt_lg_dirty_mult >= 0 && (arena->nactive >>
- opt_lg_dirty_mult) < arena->ndirty)
- arena_purge(arena);
- }
-}
-
-static inline void *
-arena_run_reg_alloc(arena_run_t *run, arena_bin_t *bin)
-{
- void *ret;
- unsigned i, mask, bit, regind;
-
- assert(run->magic == ARENA_RUN_MAGIC);
- assert(run->regs_minelm < bin->regs_mask_nelms);
-
- /*
- * Move the first check outside the loop, so that run->regs_minelm can
- * be updated unconditionally, without the possibility of updating it
- * multiple times.
- */
- i = run->regs_minelm;
- mask = run->regs_mask[i];
- if (mask != 0) {
- /* Usable allocation found. */
- bit = ffs((int)mask) - 1;
-
- regind = ((i << (LG_SIZEOF_INT + 3)) + bit);
- assert(regind < bin->nregs);
- ret = (void *)(((uintptr_t)run) + bin->reg0_offset
- + (bin->reg_size * regind));
-
- /* Clear bit. */
- mask ^= (1U << bit);
- run->regs_mask[i] = mask;
-
- arena_run_rc_incr(run, bin, ret);
-
- return (ret);
- }
-
- for (i++; i < bin->regs_mask_nelms; i++) {
- mask = run->regs_mask[i];
- if (mask != 0) {
- /* Usable allocation found. */
- bit = ffs((int)mask) - 1;
-
- regind = ((i << (LG_SIZEOF_INT + 3)) + bit);
- assert(regind < bin->nregs);
- ret = (void *)(((uintptr_t)run) + bin->reg0_offset
- + (bin->reg_size * regind));
-
- /* Clear bit. */
- mask ^= (1U << bit);
- run->regs_mask[i] = mask;
-
- /*
- * Make a note that nothing before this element
- * contains a free region.
- */
- run->regs_minelm = i; /* Low payoff: + (mask == 0); */
-
- arena_run_rc_incr(run, bin, ret);
-
- return (ret);
- }
- }
- /* Not reached. */
- assert(0);
- return (NULL);
-}
-
-static inline void
-arena_run_reg_dalloc(arena_run_t *run, arena_bin_t *bin, void *ptr, size_t size)
-{
- unsigned shift, diff, regind, elm, bit;
-
- assert(run->magic == ARENA_RUN_MAGIC);
-
- /*
- * Avoid doing division with a variable divisor if possible. Using
- * actual division here can reduce allocator throughput by over 20%!
- */
- diff = (unsigned)((uintptr_t)ptr - (uintptr_t)run - bin->reg0_offset);
-
- /* Rescale (factor powers of 2 out of the numerator and denominator). */
- shift = ffs(size) - 1;
- diff >>= shift;
- size >>= shift;
-
- if (size == 1) {
- /* The divisor was a power of 2. */
- regind = diff;
- } else {
- /*
- * To divide by a number D that is not a power of two we
- * multiply by (2^21 / D) and then right shift by 21 positions.
- *
- * X / D
- *
- * becomes
- *
- * (X * size_invs[D - 3]) >> SIZE_INV_SHIFT
- *
- * We can omit the first three elements, because we never
- * divide by 0, and 1 and 2 are both powers of two, which are
- * handled above.
- */
-#define SIZE_INV_SHIFT 21
-#define SIZE_INV(s) (((1U << SIZE_INV_SHIFT) / (s)) + 1)
- static const unsigned size_invs[] = {
- SIZE_INV(3),
- SIZE_INV(4), SIZE_INV(5), SIZE_INV(6), SIZE_INV(7),
- SIZE_INV(8), SIZE_INV(9), SIZE_INV(10), SIZE_INV(11),
- SIZE_INV(12), SIZE_INV(13), SIZE_INV(14), SIZE_INV(15),
- SIZE_INV(16), SIZE_INV(17), SIZE_INV(18), SIZE_INV(19),
- SIZE_INV(20), SIZE_INV(21), SIZE_INV(22), SIZE_INV(23),
- SIZE_INV(24), SIZE_INV(25), SIZE_INV(26), SIZE_INV(27),
- SIZE_INV(28), SIZE_INV(29), SIZE_INV(30), SIZE_INV(31)
- };
-
- if (size <= ((sizeof(size_invs) / sizeof(unsigned)) + 2))
- regind = (diff * size_invs[size - 3]) >> SIZE_INV_SHIFT;
- else
- regind = diff / size;
-#undef SIZE_INV
-#undef SIZE_INV_SHIFT
- }
- assert(diff == regind * size);
- assert(regind < bin->nregs);
-
- elm = regind >> (LG_SIZEOF_INT + 3);
- if (elm < run->regs_minelm)
- run->regs_minelm = elm;
- bit = regind - (elm << (LG_SIZEOF_INT + 3));
- assert((run->regs_mask[elm] & (1U << bit)) == 0);
- run->regs_mask[elm] |= (1U << bit);
-
- arena_run_rc_decr(run, bin, ptr);
-}
-
-static void
-arena_run_split(arena_t *arena, arena_run_t *run, size_t size, bool large,
- bool zero)
-{
- arena_chunk_t *chunk;
- size_t old_ndirty, run_ind, total_pages, need_pages, rem_pages, i;
-
- chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(run);
- old_ndirty = chunk->ndirty;
- run_ind = (unsigned)(((uintptr_t)run - (uintptr_t)chunk)
- >> PAGE_SHIFT);
- total_pages = (chunk->map[run_ind].bits & ~PAGE_MASK) >>
- PAGE_SHIFT;
- need_pages = (size >> PAGE_SHIFT);
- assert(need_pages > 0);
- assert(need_pages <= total_pages);
- rem_pages = total_pages - need_pages;
-
- arena_avail_tree_remove(&arena->runs_avail, &chunk->map[run_ind]);
- arena->nactive += need_pages;
-
- /* Keep track of trailing unused pages for later use. */
- if (rem_pages > 0) {
- chunk->map[run_ind+need_pages].bits = (rem_pages <<
- PAGE_SHIFT) | (chunk->map[run_ind+need_pages].bits &
- CHUNK_MAP_FLAGS_MASK);
- chunk->map[run_ind+total_pages-1].bits = (rem_pages <<
- PAGE_SHIFT) | (chunk->map[run_ind+total_pages-1].bits &
- CHUNK_MAP_FLAGS_MASK);
- arena_avail_tree_insert(&arena->runs_avail,
- &chunk->map[run_ind+need_pages]);
- }
-
- for (i = 0; i < need_pages; i++) {
- /* Zero if necessary. */
- if (zero) {
- if ((chunk->map[run_ind + i].bits & CHUNK_MAP_ZEROED)
- == 0) {
- memset((void *)((uintptr_t)chunk + ((run_ind
- + i) << PAGE_SHIFT)), 0, PAGE_SIZE);
- /* CHUNK_MAP_ZEROED is cleared below. */
- }
- }
-
- /* Update dirty page accounting. */
- if (chunk->map[run_ind + i].bits & CHUNK_MAP_DIRTY) {
- chunk->ndirty--;
- arena->ndirty--;
- /* CHUNK_MAP_DIRTY is cleared below. */
- }
-
- /* Initialize the chunk map. */
- if (large) {
- chunk->map[run_ind + i].bits = CHUNK_MAP_LARGE
- | CHUNK_MAP_ALLOCATED;
- } else {
- chunk->map[run_ind + i].bits = (i << CHUNK_MAP_PG_SHIFT)
- | CHUNK_MAP_ALLOCATED;
- }
- }
-
- if (large) {
- /*
- * Set the run size only in the first element for large runs.
- * This is primarily a debugging aid, since the lack of size
- * info for trailing pages only matters if the application
- * tries to operate on an interior pointer.
- */
- chunk->map[run_ind].bits |= size;
- } else {
- /*
- * Initialize the first page's refcount to 1, so that the run
- * header is protected from dirty page purging.
- */
- chunk->map[run_ind].bits += CHUNK_MAP_RC_ONE;
- }
-}
-
-static arena_chunk_t *
-arena_chunk_alloc(arena_t *arena)
-{
- arena_chunk_t *chunk;
- size_t i;
-
- if (arena->spare != NULL) {
- chunk = arena->spare;
- arena->spare = NULL;
- } else {
- bool zero;
- size_t zeroed;
-
- zero = false;
- chunk = (arena_chunk_t *)chunk_alloc(chunksize, &zero);
- if (chunk == NULL)
- return (NULL);
-#ifdef MALLOC_STATS
- arena->stats.mapped += chunksize;
-#endif
-
- chunk->arena = arena;
- chunk->dirtied = false;
-
- /*
- * Claim that no pages are in use, since the header is merely
- * overhead.
- */
- chunk->ndirty = 0;
-
- /*
- * Initialize the map to contain one maximal free untouched run.
- * Mark the pages as zeroed iff chunk_alloc() returned a zeroed
- * chunk.
- */
- zeroed = zero ? CHUNK_MAP_ZEROED : 0;
- for (i = 0; i < arena_chunk_header_npages; i++)
- chunk->map[i].bits = 0;
- chunk->map[i].bits = arena_maxclass | zeroed;
- for (i++; i < chunk_npages-1; i++)
- chunk->map[i].bits = zeroed;
- chunk->map[chunk_npages-1].bits = arena_maxclass | zeroed;
- }
-
- /* Insert the run into the runs_avail tree. */
- arena_avail_tree_insert(&arena->runs_avail,
- &chunk->map[arena_chunk_header_npages]);
-
- return (chunk);
-}
-
-static void
-arena_chunk_dealloc(arena_t *arena, arena_chunk_t *chunk)
-{
-
- if (arena->spare != NULL) {
- if (arena->spare->dirtied) {
- arena_chunk_tree_dirty_remove(
- &chunk->arena->chunks_dirty, arena->spare);
- arena->ndirty -= arena->spare->ndirty;
- }
- chunk_dealloc((void *)arena->spare, chunksize);
-#ifdef MALLOC_STATS
- arena->stats.mapped -= chunksize;
-#endif
- }
-
- /*
- * Remove run from runs_avail, regardless of whether this chunk
- * will be cached, so that the arena does not use it. Dirty page
- * flushing only uses the chunks_dirty tree, so leaving this chunk in
- * the chunks_* trees is sufficient for that purpose.
- */
- arena_avail_tree_remove(&arena->runs_avail,
- &chunk->map[arena_chunk_header_npages]);
-
- arena->spare = chunk;
-}
-
-static arena_run_t *
-arena_run_alloc(arena_t *arena, size_t size, bool large, bool zero)
-{
- arena_chunk_t *chunk;
- arena_run_t *run;
- arena_chunk_map_t *mapelm, key;
-
- assert(size <= arena_maxclass);
- assert((size & PAGE_MASK) == 0);
-
- /* Search the arena's chunks for the lowest best fit. */
- key.bits = size | CHUNK_MAP_KEY;
- mapelm = arena_avail_tree_nsearch(&arena->runs_avail, &key);
- if (mapelm != NULL) {
- arena_chunk_t *run_chunk = CHUNK_ADDR2BASE(mapelm);
- size_t pageind = ((uintptr_t)mapelm - (uintptr_t)run_chunk->map)
- / sizeof(arena_chunk_map_t);
-
- run = (arena_run_t *)((uintptr_t)run_chunk + (pageind
- << PAGE_SHIFT));
- arena_run_split(arena, run, size, large, zero);
- return (run);
- }
-
- /*
- * No usable runs. Create a new chunk from which to allocate the run.
- */
- chunk = arena_chunk_alloc(arena);
- if (chunk == NULL)
- return (NULL);
- run = (arena_run_t *)((uintptr_t)chunk + (arena_chunk_header_npages <<
- PAGE_SHIFT));
- /* Update page map. */
- arena_run_split(arena, run, size, large, zero);
- return (run);
-}
-
-#ifdef MALLOC_DEBUG
-static arena_chunk_t *
-chunks_dirty_iter_cb(arena_chunk_tree_t *tree, arena_chunk_t *chunk, void *arg)
-{
- size_t *ndirty = (size_t *)arg;
-
- assert(chunk->dirtied);
- *ndirty += chunk->ndirty;
- return (NULL);
-}
-#endif
-
-static void
-arena_purge(arena_t *arena)
-{
- arena_chunk_t *chunk;
- size_t i, npages;
-#ifdef MALLOC_DEBUG
- size_t ndirty = 0;
-
- arena_chunk_tree_dirty_iter(&arena->chunks_dirty, NULL,
- chunks_dirty_iter_cb, (void *)&ndirty);
- assert(ndirty == arena->ndirty);
-#endif
- assert((arena->nactive >> opt_lg_dirty_mult) < arena->ndirty);
-
-#ifdef MALLOC_STATS
- arena->stats.npurge++;
-#endif
-
- /*
- * Iterate downward through chunks until enough dirty memory has been
- * purged. Terminate as soon as possible in order to minimize the
- * number of system calls, even if a chunk has only been partially
- * purged.
- */
-
- while ((arena->nactive >> (opt_lg_dirty_mult + 1)) < arena->ndirty) {
- chunk = arena_chunk_tree_dirty_last(&arena->chunks_dirty);
- assert(chunk != NULL);
-
- for (i = chunk_npages - 1; chunk->ndirty > 0; i--) {
- assert(i >= arena_chunk_header_npages);
- if (chunk->map[i].bits & CHUNK_MAP_DIRTY) {
- chunk->map[i].bits ^= CHUNK_MAP_DIRTY;
- /* Find adjacent dirty run(s). */
- for (npages = 1; i > arena_chunk_header_npages
- && (chunk->map[i - 1].bits &
- CHUNK_MAP_DIRTY); npages++) {
- i--;
- chunk->map[i].bits ^= CHUNK_MAP_DIRTY;
- }
- chunk->ndirty -= npages;
- arena->ndirty -= npages;
-
- madvise((void *)((uintptr_t)chunk + (i <<
- PAGE_SHIFT)), (npages << PAGE_SHIFT),
- MADV_FREE);
-#ifdef MALLOC_STATS
- arena->stats.nmadvise++;
- arena->stats.purged += npages;
-#endif
- if ((arena->nactive >> (opt_lg_dirty_mult + 1))
- >= arena->ndirty)
- break;
- }
- }
-
- if (chunk->ndirty == 0) {
- arena_chunk_tree_dirty_remove(&arena->chunks_dirty,
- chunk);
- chunk->dirtied = false;
- }
- }
-}
-
-static void
-arena_run_dalloc(arena_t *arena, arena_run_t *run, bool dirty)
-{
- arena_chunk_t *chunk;
- size_t size, run_ind, run_pages;
-
- chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(run);
- run_ind = (size_t)(((uintptr_t)run - (uintptr_t)chunk)
- >> PAGE_SHIFT);
- assert(run_ind >= arena_chunk_header_npages);
- assert(run_ind < chunk_npages);
- if ((chunk->map[run_ind].bits & CHUNK_MAP_LARGE) != 0)
- size = chunk->map[run_ind].bits & ~PAGE_MASK;
- else
- size = run->bin->run_size;
- run_pages = (size >> PAGE_SHIFT);
- arena->nactive -= run_pages;
-
- /* Mark pages as unallocated in the chunk map. */
- if (dirty) {
- size_t i;
-
- for (i = 0; i < run_pages; i++) {
- /*
- * When (dirty == true), *all* pages within the run
- * need to have their dirty bits set, because only
- * small runs can create a mixture of clean/dirty
- * pages, but such runs are passed to this function
- * with (dirty == false).
- */
- assert((chunk->map[run_ind + i].bits & CHUNK_MAP_DIRTY)
- == 0);
- chunk->ndirty++;
- arena->ndirty++;
- chunk->map[run_ind + i].bits = CHUNK_MAP_DIRTY;
- }
- } else {
- size_t i;
-
- for (i = 0; i < run_pages; i++) {
- chunk->map[run_ind + i].bits &= ~(CHUNK_MAP_LARGE |
- CHUNK_MAP_ALLOCATED);
- }
- }
- chunk->map[run_ind].bits = size | (chunk->map[run_ind].bits &
- CHUNK_MAP_FLAGS_MASK);
- chunk->map[run_ind+run_pages-1].bits = size |
- (chunk->map[run_ind+run_pages-1].bits & CHUNK_MAP_FLAGS_MASK);
-
- /* Try to coalesce forward. */
- if (run_ind + run_pages < chunk_npages &&
- (chunk->map[run_ind+run_pages].bits & CHUNK_MAP_ALLOCATED) == 0) {
- size_t nrun_size = chunk->map[run_ind+run_pages].bits &
- ~PAGE_MASK;
-
- /*
- * Remove successor from runs_avail; the coalesced run is
- * inserted later.
- */
- arena_avail_tree_remove(&arena->runs_avail,
- &chunk->map[run_ind+run_pages]);
-
- size += nrun_size;
- run_pages = size >> PAGE_SHIFT;
-
- assert((chunk->map[run_ind+run_pages-1].bits & ~PAGE_MASK)
- == nrun_size);
- chunk->map[run_ind].bits = size | (chunk->map[run_ind].bits &
- CHUNK_MAP_FLAGS_MASK);
- chunk->map[run_ind+run_pages-1].bits = size |
- (chunk->map[run_ind+run_pages-1].bits &
- CHUNK_MAP_FLAGS_MASK);
- }
-
- /* Try to coalesce backward. */
- if (run_ind > arena_chunk_header_npages && (chunk->map[run_ind-1].bits &
- CHUNK_MAP_ALLOCATED) == 0) {
- size_t prun_size = chunk->map[run_ind-1].bits & ~PAGE_MASK;
-
- run_ind -= prun_size >> PAGE_SHIFT;
-
- /*
- * Remove predecessor from runs_avail; the coalesced run is
- * inserted later.
- */
- arena_avail_tree_remove(&arena->runs_avail,
- &chunk->map[run_ind]);
-
- size += prun_size;
- run_pages = size >> PAGE_SHIFT;
-
- assert((chunk->map[run_ind].bits & ~PAGE_MASK) == prun_size);
- chunk->map[run_ind].bits = size | (chunk->map[run_ind].bits &
- CHUNK_MAP_FLAGS_MASK);
- chunk->map[run_ind+run_pages-1].bits = size |
- (chunk->map[run_ind+run_pages-1].bits &
- CHUNK_MAP_FLAGS_MASK);
- }
-
- /* Insert into runs_avail, now that coalescing is complete. */
- arena_avail_tree_insert(&arena->runs_avail, &chunk->map[run_ind]);
-
- /*
- * Deallocate chunk if it is now completely unused. The bit
- * manipulation checks whether the first run is unallocated and extends
- * to the end of the chunk.
- */
- if ((chunk->map[arena_chunk_header_npages].bits & (~PAGE_MASK |
- CHUNK_MAP_ALLOCATED)) == arena_maxclass)
- arena_chunk_dealloc(arena, chunk);
-
- /*
- * It is okay to do dirty page processing even if the chunk was
- * deallocated above, since in that case it is the spare. Waiting
- * until after possible chunk deallocation to do dirty processing
- * allows for an old spare to be fully deallocated, thus decreasing the
- * chances of spuriously crossing the dirty page purging threshold.
- */
- if (dirty) {
- if (chunk->dirtied == false) {
- arena_chunk_tree_dirty_insert(&arena->chunks_dirty,
- chunk);
- chunk->dirtied = true;
- }
-
- /* Enforce opt_lg_dirty_mult. */
- if (opt_lg_dirty_mult >= 0 && (arena->nactive >>
- opt_lg_dirty_mult) < arena->ndirty)
- arena_purge(arena);
- }
-}
-
-static void
-arena_run_trim_head(arena_t *arena, arena_chunk_t *chunk, arena_run_t *run,
- size_t oldsize, size_t newsize)
-{
- size_t pageind = ((uintptr_t)run - (uintptr_t)chunk) >> PAGE_SHIFT;
- size_t head_npages = (oldsize - newsize) >> PAGE_SHIFT;
-
- assert(oldsize > newsize);
-
- /*
- * Update the chunk map so that arena_run_dalloc() can treat the
- * leading run as separately allocated.
- */
- assert((chunk->map[pageind].bits & CHUNK_MAP_DIRTY) == 0);
- chunk->map[pageind].bits = (oldsize - newsize) | CHUNK_MAP_LARGE |
- CHUNK_MAP_ALLOCATED;
- assert((chunk->map[pageind+head_npages].bits & CHUNK_MAP_DIRTY) == 0);
- chunk->map[pageind+head_npages].bits = newsize | CHUNK_MAP_LARGE |
- CHUNK_MAP_ALLOCATED;
-
- arena_run_dalloc(arena, run, false);
-}
-
-static void
-arena_run_trim_tail(arena_t *arena, arena_chunk_t *chunk, arena_run_t *run,
- size_t oldsize, size_t newsize, bool dirty)
-{
- size_t pageind = ((uintptr_t)run - (uintptr_t)chunk) >> PAGE_SHIFT;
- size_t npages = newsize >> PAGE_SHIFT;
-
- assert(oldsize > newsize);
-
- /*
- * Update the chunk map so that arena_run_dalloc() can treat the
- * trailing run as separately allocated.
- */
- assert((chunk->map[pageind].bits & CHUNK_MAP_DIRTY) == 0);
- chunk->map[pageind].bits = newsize | CHUNK_MAP_LARGE |
- CHUNK_MAP_ALLOCATED;
- assert((chunk->map[pageind+npages].bits & CHUNK_MAP_DIRTY) == 0);
- chunk->map[pageind+npages].bits = (oldsize - newsize) | CHUNK_MAP_LARGE
- | CHUNK_MAP_ALLOCATED;
-
- arena_run_dalloc(arena, (arena_run_t *)((uintptr_t)run + newsize),
- dirty);
-}
-
-static arena_run_t *
-arena_bin_nonfull_run_get(arena_t *arena, arena_bin_t *bin)
-{
- arena_chunk_map_t *mapelm;
- arena_run_t *run;
- unsigned i, remainder;
-
- /* Look for a usable run. */
- mapelm = arena_run_tree_first(&bin->runs);
- if (mapelm != NULL) {
- arena_chunk_t *chunk;
- size_t pageind;
-
- /* run is guaranteed to have available space. */
- arena_run_tree_remove(&bin->runs, mapelm);
-
- chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(mapelm);
- pageind = (((uintptr_t)mapelm - (uintptr_t)chunk->map) /
- sizeof(arena_chunk_map_t));
- run = (arena_run_t *)((uintptr_t)chunk + (uintptr_t)((pageind -
- ((mapelm->bits & CHUNK_MAP_PG_MASK) >> CHUNK_MAP_PG_SHIFT))
- << PAGE_SHIFT));
-#ifdef MALLOC_STATS
- bin->stats.reruns++;
-#endif
- return (run);
- }
- /* No existing runs have any space available. */
-
- /* Allocate a new run. */
- run = arena_run_alloc(arena, bin->run_size, false, false);
- if (run == NULL)
- return (NULL);
-
- /* Initialize run internals. */
- run->bin = bin;
-
- for (i = 0; i < bin->regs_mask_nelms - 1; i++)
- run->regs_mask[i] = UINT_MAX;
- remainder = bin->nregs & ((1U << (LG_SIZEOF_INT + 3)) - 1);
- if (remainder == 0)
- run->regs_mask[i] = UINT_MAX;
- else {
- /* The last element has spare bits that need to be unset. */
- run->regs_mask[i] = (UINT_MAX >> ((1U << (LG_SIZEOF_INT + 3))
- - remainder));
- }
-
- run->regs_minelm = 0;
-
- run->nfree = bin->nregs;
-#ifdef MALLOC_DEBUG
- run->magic = ARENA_RUN_MAGIC;
-#endif
-
-#ifdef MALLOC_STATS
- bin->stats.nruns++;
- bin->stats.curruns++;
- if (bin->stats.curruns > bin->stats.highruns)
- bin->stats.highruns = bin->stats.curruns;
-#endif
- return (run);
-}
-
-/* bin->runcur must have space available before this function is called. */
-static inline void *
-arena_bin_malloc_easy(arena_t *arena, arena_bin_t *bin, arena_run_t *run)
-{
- void *ret;
-
- assert(run->magic == ARENA_RUN_MAGIC);
- assert(run->nfree > 0);
-
- ret = arena_run_reg_alloc(run, bin);
- assert(ret != NULL);
- run->nfree--;
-
- return (ret);
-}
-
-/* Re-fill bin->runcur, then call arena_bin_malloc_easy(). */
-static void *
-arena_bin_malloc_hard(arena_t *arena, arena_bin_t *bin)
-{
-
- bin->runcur = arena_bin_nonfull_run_get(arena, bin);
- if (bin->runcur == NULL)
- return (NULL);
- assert(bin->runcur->magic == ARENA_RUN_MAGIC);
- assert(bin->runcur->nfree > 0);
-
- return (arena_bin_malloc_easy(arena, bin, bin->runcur));
-}
-
-/*
- * Calculate bin->run_size such that it meets the following constraints:
- *
- * *) bin->run_size >= min_run_size
- * *) bin->run_size <= arena_maxclass
- * *) bin->run_size <= RUN_MAX_SMALL
- * *) run header overhead <= RUN_MAX_OVRHD (or header overhead relaxed).
- * *) run header size < PAGE_SIZE
- *
- * bin->nregs, bin->regs_mask_nelms, and bin->reg0_offset are
- * also calculated here, since these settings are all interdependent.
- */
-static size_t
-arena_bin_run_size_calc(arena_bin_t *bin, size_t min_run_size)
-{
- size_t try_run_size, good_run_size;
- unsigned good_nregs, good_mask_nelms, good_reg0_offset;
- unsigned try_nregs, try_mask_nelms, try_reg0_offset;
-
- assert(min_run_size >= PAGE_SIZE);
- assert(min_run_size <= arena_maxclass);
- assert(min_run_size <= RUN_MAX_SMALL);
-
- /*
- * Calculate known-valid settings before entering the run_size
- * expansion loop, so that the first part of the loop always copies
- * valid settings.
- *
- * The do..while loop iteratively reduces the number of regions until
- * the run header and the regions no longer overlap. A closed formula
- * would be quite messy, since there is an interdependency between the
- * header's mask length and the number of regions.
- */
- try_run_size = min_run_size;
- try_nregs = ((try_run_size - sizeof(arena_run_t)) / bin->reg_size)
- + 1; /* Counter-act try_nregs-- in loop. */
- do {
- try_nregs--;
- try_mask_nelms = (try_nregs >> (LG_SIZEOF_INT + 3)) +
- ((try_nregs & ((1U << (LG_SIZEOF_INT + 3)) - 1)) ? 1 : 0);
- try_reg0_offset = try_run_size - (try_nregs * bin->reg_size);
- } while (sizeof(arena_run_t) + (sizeof(unsigned) * (try_mask_nelms - 1))
- > try_reg0_offset);
-
- /* run_size expansion loop. */
- do {
- /*
- * Copy valid settings before trying more aggressive settings.
- */
- good_run_size = try_run_size;
- good_nregs = try_nregs;
- good_mask_nelms = try_mask_nelms;
- good_reg0_offset = try_reg0_offset;
-
- /* Try more aggressive settings. */
- try_run_size += PAGE_SIZE;
- try_nregs = ((try_run_size - sizeof(arena_run_t)) /
- bin->reg_size) + 1; /* Counter-act try_nregs-- in loop. */
- do {
- try_nregs--;
- try_mask_nelms = (try_nregs >> (LG_SIZEOF_INT + 3)) +
- ((try_nregs & ((1U << (LG_SIZEOF_INT + 3)) - 1)) ?
- 1 : 0);
- try_reg0_offset = try_run_size - (try_nregs *
- bin->reg_size);
- } while (sizeof(arena_run_t) + (sizeof(unsigned) *
- (try_mask_nelms - 1)) > try_reg0_offset);
- } while (try_run_size <= arena_maxclass && try_run_size <= RUN_MAX_SMALL
- && RUN_MAX_OVRHD * (bin->reg_size << 3) > RUN_MAX_OVRHD_RELAX
- && (try_reg0_offset << RUN_BFP) > RUN_MAX_OVRHD * try_run_size
- && (sizeof(arena_run_t) + (sizeof(unsigned) * (try_mask_nelms - 1)))
- < PAGE_SIZE);
-
- assert(sizeof(arena_run_t) + (sizeof(unsigned) * (good_mask_nelms - 1))
- <= good_reg0_offset);
- assert((good_mask_nelms << (LG_SIZEOF_INT + 3)) >= good_nregs);
-
- /* Copy final settings. */
- bin->run_size = good_run_size;
- bin->nregs = good_nregs;
- bin->regs_mask_nelms = good_mask_nelms;
- bin->reg0_offset = good_reg0_offset;
-
- return (good_run_size);
-}
-
-#ifdef MALLOC_TCACHE
-static inline void
-tcache_event(tcache_t *tcache)
-{
-
- if (tcache_gc_incr == 0)
- return;
-
- tcache->ev_cnt++;
- assert(tcache->ev_cnt <= tcache_gc_incr);
- if (tcache->ev_cnt >= tcache_gc_incr) {
- size_t binind = tcache->next_gc_bin;
- tcache_bin_t *tbin = tcache->tbins[binind];
-
- if (tbin != NULL) {
- if (tbin->high_water == 0) {
- /*
- * This bin went completely unused for an
- * entire GC cycle, so throw away the tbin.
- */
- assert(tbin->ncached == 0);
- tcache_bin_destroy(tcache, tbin, binind);
- tcache->tbins[binind] = NULL;
- } else {
- if (tbin->low_water > 0) {
- /*
- * Flush (ceiling) half of the objects
- * below the low water mark.
- */
- tcache_bin_flush(tbin, binind,
- tbin->ncached - (tbin->low_water >>
- 1) - (tbin->low_water & 1));
- }
- tbin->low_water = tbin->ncached;
- tbin->high_water = tbin->ncached;
- }
- }
-
- tcache->next_gc_bin++;
- if (tcache->next_gc_bin == nbins)
- tcache->next_gc_bin = 0;
- tcache->ev_cnt = 0;
- }
-}
-
-static inline void *
-tcache_bin_alloc(tcache_bin_t *tbin)
-{
-
- if (tbin->ncached == 0)
- return (NULL);
- tbin->ncached--;
- if (tbin->ncached < tbin->low_water)
- tbin->low_water = tbin->ncached;
- return (tbin->slots[tbin->ncached]);
-}
-
-static void
-tcache_bin_fill(tcache_t *tcache, tcache_bin_t *tbin, size_t binind)
-{
- arena_t *arena;
- arena_bin_t *bin;
- arena_run_t *run;
- void *ptr;
- unsigned i;
-
- assert(tbin->ncached == 0);
-
- arena = tcache->arena;
- bin = &arena->bins[binind];
- malloc_spin_lock(&arena->lock);
- for (i = 0; i < (tcache_nslots >> 1); i++) {
- if ((run = bin->runcur) != NULL && run->nfree > 0)
- ptr = arena_bin_malloc_easy(arena, bin, run);
- else
- ptr = arena_bin_malloc_hard(arena, bin);
- if (ptr == NULL)
- break;
- /*
- * Fill tbin such that the objects lowest in memory are used
- * first.
- */
- tbin->slots[(tcache_nslots >> 1) - 1 - i] = ptr;
- }
-#ifdef MALLOC_STATS
- bin->stats.nfills++;
- bin->stats.nrequests += tbin->tstats.nrequests;
- if (bin->reg_size <= small_maxclass) {
- arena->stats.nmalloc_small += (i - tbin->ncached);
- arena->stats.allocated_small += (i - tbin->ncached) *
- bin->reg_size;
- arena->stats.nmalloc_small += tbin->tstats.nrequests;
- } else {
- arena->stats.nmalloc_medium += (i - tbin->ncached);
- arena->stats.allocated_medium += (i - tbin->ncached) *
- bin->reg_size;
- arena->stats.nmalloc_medium += tbin->tstats.nrequests;
- }
- tbin->tstats.nrequests = 0;
-#endif
- malloc_spin_unlock(&arena->lock);
- tbin->ncached = i;
- if (tbin->ncached > tbin->high_water)
- tbin->high_water = tbin->ncached;
-}
-
-static inline void *
-tcache_alloc(tcache_t *tcache, size_t size, bool zero)
-{
- void *ret;
- tcache_bin_t *tbin;
- size_t binind;
-
- if (size <= small_maxclass)
- binind = small_size2bin[size];
- else {
- binind = mbin0 + ((MEDIUM_CEILING(size) - medium_min) >>
- lg_mspace);
- }
- assert(binind < nbins);
- tbin = tcache->tbins[binind];
- if (tbin == NULL) {
- tbin = tcache_bin_create(tcache->arena);
- if (tbin == NULL)
- return (NULL);
- tcache->tbins[binind] = tbin;
- }
-
- ret = tcache_bin_alloc(tbin);
- if (ret == NULL) {
- ret = tcache_alloc_hard(tcache, tbin, binind);
- if (ret == NULL)
- return (NULL);
- }
-
- if (zero == false) {
- if (opt_junk)
- memset(ret, 0xa5, size);
- else if (opt_zero)
- memset(ret, 0, size);
- } else
- memset(ret, 0, size);
-
-#ifdef MALLOC_STATS
- tbin->tstats.nrequests++;
-#endif
- tcache_event(tcache);
- return (ret);
-}
-
-static void *
-tcache_alloc_hard(tcache_t *tcache, tcache_bin_t *tbin, size_t binind)
-{
- void *ret;
-
- tcache_bin_fill(tcache, tbin, binind);
- ret = tcache_bin_alloc(tbin);
-
- return (ret);
-}
-#endif
-
-static inline void *
-arena_malloc_small(arena_t *arena, size_t size, bool zero)
-{
- void *ret;
- arena_bin_t *bin;
- arena_run_t *run;
- size_t binind;
-
- binind = small_size2bin[size];
- assert(binind < mbin0);
- bin = &arena->bins[binind];
- size = bin->reg_size;
-
- malloc_spin_lock(&arena->lock);
- if ((run = bin->runcur) != NULL && run->nfree > 0)
- ret = arena_bin_malloc_easy(arena, bin, run);
- else
- ret = arena_bin_malloc_hard(arena, bin);
-
- if (ret == NULL) {
- malloc_spin_unlock(&arena->lock);
- return (NULL);
- }
-
-#ifdef MALLOC_STATS
-# ifdef MALLOC_TCACHE
- if (__isthreaded == false) {
-# endif
- bin->stats.nrequests++;
- arena->stats.nmalloc_small++;
-# ifdef MALLOC_TCACHE
- }
-# endif
- arena->stats.allocated_small += size;
-#endif
- malloc_spin_unlock(&arena->lock);
-
- if (zero == false) {
- if (opt_junk)
- memset(ret, 0xa5, size);
- else if (opt_zero)
- memset(ret, 0, size);
- } else
- memset(ret, 0, size);
-
- return (ret);
-}
-
-static void *
-arena_malloc_medium(arena_t *arena, size_t size, bool zero)
-{
- void *ret;
- arena_bin_t *bin;
- arena_run_t *run;
- size_t binind;
-
- size = MEDIUM_CEILING(size);
- binind = mbin0 + ((size - medium_min) >> lg_mspace);
- assert(binind < nbins);
- bin = &arena->bins[binind];
- assert(bin->reg_size == size);
-
- malloc_spin_lock(&arena->lock);
- if ((run = bin->runcur) != NULL && run->nfree > 0)
- ret = arena_bin_malloc_easy(arena, bin, run);
- else
- ret = arena_bin_malloc_hard(arena, bin);
-
- if (ret == NULL) {
- malloc_spin_unlock(&arena->lock);
- return (NULL);
- }
-
-#ifdef MALLOC_STATS
-# ifdef MALLOC_TCACHE
- if (__isthreaded == false) {
-# endif
- bin->stats.nrequests++;
- arena->stats.nmalloc_medium++;
-# ifdef MALLOC_TCACHE
- }
-# endif
- arena->stats.allocated_medium += size;
-#endif
- malloc_spin_unlock(&arena->lock);
-
- if (zero == false) {
- if (opt_junk)
- memset(ret, 0xa5, size);
- else if (opt_zero)
- memset(ret, 0, size);
- } else
- memset(ret, 0, size);
-
- return (ret);
-}
-
-static void *
-arena_malloc_large(arena_t *arena, size_t size, bool zero)
-{
- void *ret;
-
- /* Large allocation. */
- size = PAGE_CEILING(size);
- malloc_spin_lock(&arena->lock);
- ret = (void *)arena_run_alloc(arena, size, true, zero);
- if (ret == NULL) {
- malloc_spin_unlock(&arena->lock);
- return (NULL);
- }
-#ifdef MALLOC_STATS
- arena->stats.nmalloc_large++;
- arena->stats.allocated_large += size;
- arena->stats.lstats[(size >> PAGE_SHIFT) - 1].nrequests++;
- arena->stats.lstats[(size >> PAGE_SHIFT) - 1].curruns++;
- if (arena->stats.lstats[(size >> PAGE_SHIFT) - 1].curruns >
- arena->stats.lstats[(size >> PAGE_SHIFT) - 1].highruns) {
- arena->stats.lstats[(size >> PAGE_SHIFT) - 1].highruns =
- arena->stats.lstats[(size >> PAGE_SHIFT) - 1].curruns;
- }
-#endif
- malloc_spin_unlock(&arena->lock);
-
- if (zero == false) {
- if (opt_junk)
- memset(ret, 0xa5, size);
- else if (opt_zero)
- memset(ret, 0, size);
- }
-
- return (ret);
-}
-
-static inline void *
-arena_malloc(size_t size, bool zero)
-{
-
- assert(size != 0);
- assert(QUANTUM_CEILING(size) <= arena_maxclass);
-
- if (size <= bin_maxclass) {
-#ifdef MALLOC_TCACHE
- if (__isthreaded && tcache_nslots) {
- tcache_t *tcache = tcache_tls;
- if ((uintptr_t)tcache > (uintptr_t)1)
- return (tcache_alloc(tcache, size, zero));
- else if (tcache == NULL) {
- tcache = tcache_create(choose_arena());
- if (tcache == NULL)
- return (NULL);
- return (tcache_alloc(tcache, size, zero));
- }
- }
-#endif
- if (size <= small_maxclass) {
- return (arena_malloc_small(choose_arena(), size,
- zero));
- } else {
- return (arena_malloc_medium(choose_arena(),
- size, zero));
- }
- } else
- return (arena_malloc_large(choose_arena(), size, zero));
-}
-
-static inline void *
-imalloc(size_t size)
-{
-
- assert(size != 0);
-
- if (size <= arena_maxclass)
- return (arena_malloc(size, false));
- else
- return (huge_malloc(size, false));
-}
-
-static inline void *
-icalloc(size_t size)
-{
-
- if (size <= arena_maxclass)
- return (arena_malloc(size, true));
- else
- return (huge_malloc(size, true));
-}
-
-/* Only handles large allocations that require more than page alignment. */
-static void *
-arena_palloc(arena_t *arena, size_t alignment, size_t size, size_t alloc_size)
-{
- void *ret;
- size_t offset;
- arena_chunk_t *chunk;
-
- assert((size & PAGE_MASK) == 0);
- assert((alignment & PAGE_MASK) == 0);
-
- malloc_spin_lock(&arena->lock);
- ret = (void *)arena_run_alloc(arena, alloc_size, true, false);
- if (ret == NULL) {
- malloc_spin_unlock(&arena->lock);
- return (NULL);
- }
-
- chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ret);
-
- offset = (uintptr_t)ret & (alignment - 1);
- assert((offset & PAGE_MASK) == 0);
- assert(offset < alloc_size);
- if (offset == 0)
- arena_run_trim_tail(arena, chunk, ret, alloc_size, size, false);
- else {
- size_t leadsize, trailsize;
-
- leadsize = alignment - offset;
- if (leadsize > 0) {
- arena_run_trim_head(arena, chunk, ret, alloc_size,
- alloc_size - leadsize);
- ret = (void *)((uintptr_t)ret + leadsize);
- }
-
- trailsize = alloc_size - leadsize - size;
- if (trailsize != 0) {
- /* Trim trailing space. */
- assert(trailsize < alloc_size);
- arena_run_trim_tail(arena, chunk, ret, size + trailsize,
- size, false);
- }
- }
-
-#ifdef MALLOC_STATS
- arena->stats.nmalloc_large++;
- arena->stats.allocated_large += size;
- arena->stats.lstats[(size >> PAGE_SHIFT) - 1].nrequests++;
- arena->stats.lstats[(size >> PAGE_SHIFT) - 1].curruns++;
- if (arena->stats.lstats[(size >> PAGE_SHIFT) - 1].curruns >
- arena->stats.lstats[(size >> PAGE_SHIFT) - 1].highruns) {
- arena->stats.lstats[(size >> PAGE_SHIFT) - 1].highruns =
- arena->stats.lstats[(size >> PAGE_SHIFT) - 1].curruns;
- }
-#endif
- malloc_spin_unlock(&arena->lock);
-
- if (opt_junk)
- memset(ret, 0xa5, size);
- else if (opt_zero)
- memset(ret, 0, size);
- return (ret);
-}
-
-static inline void *
-ipalloc(size_t alignment, size_t size)
-{
- void *ret;
- size_t ceil_size;
-
- /*
- * Round size up to the nearest multiple of alignment.
- *
- * This done, we can take advantage of the fact that for each small
- * size class, every object is aligned at the smallest power of two
- * that is non-zero in the base two representation of the size. For
- * example:
- *
- * Size | Base 2 | Minimum alignment
- * -----+----------+------------------
- * 96 | 1100000 | 32
- * 144 | 10100000 | 32
- * 192 | 11000000 | 64
- *
- * Depending on runtime settings, it is possible that arena_malloc()
- * will further round up to a power of two, but that never causes
- * correctness issues.
- */
- ceil_size = (size + (alignment - 1)) & (-alignment);
- /*
- * (ceil_size < size) protects against the combination of maximal
- * alignment and size greater than maximal alignment.
- */
- if (ceil_size < size) {
- /* size_t overflow. */
- return (NULL);
- }
-
- if (ceil_size <= PAGE_SIZE || (alignment <= PAGE_SIZE
- && ceil_size <= arena_maxclass))
- ret = arena_malloc(ceil_size, false);
- else {
- size_t run_size;
-
- /*
- * We can't achieve subpage alignment, so round up alignment
- * permanently; it makes later calculations simpler.
- */
- alignment = PAGE_CEILING(alignment);
- ceil_size = PAGE_CEILING(size);
- /*
- * (ceil_size < size) protects against very large sizes within
- * PAGE_SIZE of SIZE_T_MAX.
- *
- * (ceil_size + alignment < ceil_size) protects against the
- * combination of maximal alignment and ceil_size large enough
- * to cause overflow. This is similar to the first overflow
- * check above, but it needs to be repeated due to the new
- * ceil_size value, which may now be *equal* to maximal
- * alignment, whereas before we only detected overflow if the
- * original size was *greater* than maximal alignment.
- */
- if (ceil_size < size || ceil_size + alignment < ceil_size) {
- /* size_t overflow. */
- return (NULL);
- }
-
- /*
- * Calculate the size of the over-size run that arena_palloc()
- * would need to allocate in order to guarantee the alignment.
- */
- if (ceil_size >= alignment)
- run_size = ceil_size + alignment - PAGE_SIZE;
- else {
- /*
- * It is possible that (alignment << 1) will cause
- * overflow, but it doesn't matter because we also
- * subtract PAGE_SIZE, which in the case of overflow
- * leaves us with a very large run_size. That causes
- * the first conditional below to fail, which means
- * that the bogus run_size value never gets used for
- * anything important.
- */
- run_size = (alignment << 1) - PAGE_SIZE;
- }
-
- if (run_size <= arena_maxclass) {
- ret = arena_palloc(choose_arena(), alignment, ceil_size,
- run_size);
- } else if (alignment <= chunksize)
- ret = huge_malloc(ceil_size, false);
- else
- ret = huge_palloc(alignment, ceil_size);
- }
-
- assert(((uintptr_t)ret & (alignment - 1)) == 0);
- return (ret);
-}
-
-static bool
-arena_is_large(const void *ptr)
-{
- arena_chunk_t *chunk;
- size_t pageind, mapbits;
-
- assert(ptr != NULL);
- assert(CHUNK_ADDR2BASE(ptr) != ptr);
-
- chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);
- pageind = (((uintptr_t)ptr - (uintptr_t)chunk) >> PAGE_SHIFT);
- mapbits = chunk->map[pageind].bits;
- assert((mapbits & CHUNK_MAP_ALLOCATED) != 0);
- return ((mapbits & CHUNK_MAP_LARGE) != 0);
-}
-
-/* Return the size of the allocation pointed to by ptr. */
-static size_t
-arena_salloc(const void *ptr)
-{
- size_t ret;
- arena_chunk_t *chunk;
- size_t pageind, mapbits;
-
- assert(ptr != NULL);
- assert(CHUNK_ADDR2BASE(ptr) != ptr);
-
- chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);
- pageind = (((uintptr_t)ptr - (uintptr_t)chunk) >> PAGE_SHIFT);
- mapbits = chunk->map[pageind].bits;
- assert((mapbits & CHUNK_MAP_ALLOCATED) != 0);
- if ((mapbits & CHUNK_MAP_LARGE) == 0) {
- arena_run_t *run = (arena_run_t *)((uintptr_t)chunk +
- (uintptr_t)((pageind - ((mapbits & CHUNK_MAP_PG_MASK) >>
- CHUNK_MAP_PG_SHIFT)) << PAGE_SHIFT));
- assert(run->magic == ARENA_RUN_MAGIC);
- ret = run->bin->reg_size;
- } else {
- ret = mapbits & ~PAGE_MASK;
- assert(ret != 0);
- }
-
- return (ret);
-}
-
-static inline size_t
-isalloc(const void *ptr)
-{
- size_t ret;
- arena_chunk_t *chunk;
-
- assert(ptr != NULL);
-
- chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);
- if (chunk != ptr) {
- /* Region. */
- assert(chunk->arena->magic == ARENA_MAGIC);
-
- ret = arena_salloc(ptr);
- } else {
- extent_node_t *node, key;
-
- /* Chunk (huge allocation). */
-
- malloc_mutex_lock(&huge_mtx);
-
- /* Extract from tree of huge allocations. */
- key.addr = __DECONST(void *, ptr);
- node = extent_tree_ad_search(&huge, &key);
- assert(node != NULL);
-
- ret = node->size;
-
- malloc_mutex_unlock(&huge_mtx);
- }
-
- return (ret);
-}
-
-static inline void
-arena_dalloc_bin(arena_t *arena, arena_chunk_t *chunk, void *ptr,
- arena_chunk_map_t *mapelm)
-{
- size_t pageind;
- arena_run_t *run;
- arena_bin_t *bin;
- size_t size;
-
- pageind = (((uintptr_t)ptr - (uintptr_t)chunk) >> PAGE_SHIFT);
- run = (arena_run_t *)((uintptr_t)chunk + (uintptr_t)((pageind -
- ((mapelm->bits & CHUNK_MAP_PG_MASK) >> CHUNK_MAP_PG_SHIFT)) <<
- PAGE_SHIFT));
- assert(run->magic == ARENA_RUN_MAGIC);
- bin = run->bin;
- size = bin->reg_size;
-
- if (opt_junk)
- memset(ptr, 0x5a, size);
-
- arena_run_reg_dalloc(run, bin, ptr, size);
- run->nfree++;
-
- if (run->nfree == bin->nregs)
- arena_dalloc_bin_run(arena, chunk, run, bin);
- else if (run->nfree == 1 && run != bin->runcur) {
- /*
- * Make sure that bin->runcur always refers to the lowest
- * non-full run, if one exists.
- */
- if (bin->runcur == NULL)
- bin->runcur = run;
- else if ((uintptr_t)run < (uintptr_t)bin->runcur) {
- /* Switch runcur. */
- if (bin->runcur->nfree > 0) {
- arena_chunk_t *runcur_chunk =
- CHUNK_ADDR2BASE(bin->runcur);
- size_t runcur_pageind =
- (((uintptr_t)bin->runcur -
- (uintptr_t)runcur_chunk)) >> PAGE_SHIFT;
- arena_chunk_map_t *runcur_mapelm =
- &runcur_chunk->map[runcur_pageind];
-
- /* Insert runcur. */
- arena_run_tree_insert(&bin->runs,
- runcur_mapelm);
- }
- bin->runcur = run;
- } else {
- size_t run_pageind = (((uintptr_t)run -
- (uintptr_t)chunk)) >> PAGE_SHIFT;
- arena_chunk_map_t *run_mapelm =
- &chunk->map[run_pageind];
-
- assert(arena_run_tree_search(&bin->runs, run_mapelm) ==
- NULL);
- arena_run_tree_insert(&bin->runs, run_mapelm);
- }
- }
-
-#ifdef MALLOC_STATS
- if (size <= small_maxclass) {
- arena->stats.allocated_small -= size;
- arena->stats.ndalloc_small++;
- } else {
- arena->stats.allocated_medium -= size;
- arena->stats.ndalloc_medium++;
- }
-#endif
-}
-
-static void
-arena_dalloc_bin_run(arena_t *arena, arena_chunk_t *chunk, arena_run_t *run,
- arena_bin_t *bin)
-{
- size_t run_ind;
-
- /* Deallocate run. */
- if (run == bin->runcur)
- bin->runcur = NULL;
- else if (bin->nregs != 1) {
- size_t run_pageind = (((uintptr_t)run -
- (uintptr_t)chunk)) >> PAGE_SHIFT;
- arena_chunk_map_t *run_mapelm =
- &chunk->map[run_pageind];
- /*
- * This block's conditional is necessary because if the
- * run only contains one region, then it never gets
- * inserted into the non-full runs tree.
- */
- arena_run_tree_remove(&bin->runs, run_mapelm);
- }
- /*
- * Mark the first page as dirty. The dirty bit for every other page in
- * the run is already properly set, which means we can call
- * arena_run_dalloc(..., false), thus potentially avoiding the needless
- * creation of many dirty pages.
- */
- run_ind = (size_t)(((uintptr_t)run - (uintptr_t)chunk) >> PAGE_SHIFT);
- assert((chunk->map[run_ind].bits & CHUNK_MAP_DIRTY) == 0);
- chunk->map[run_ind].bits |= CHUNK_MAP_DIRTY;
- chunk->ndirty++;
- arena->ndirty++;
-
-#ifdef MALLOC_DEBUG
- run->magic = 0;
-#endif
- arena_run_dalloc(arena, run, false);
-#ifdef MALLOC_STATS
- bin->stats.curruns--;
-#endif
-
- if (chunk->dirtied == false) {
- arena_chunk_tree_dirty_insert(&arena->chunks_dirty, chunk);
- chunk->dirtied = true;
- }
- /* Enforce opt_lg_dirty_mult. */
- if (opt_lg_dirty_mult >= 0 && (arena->nactive >> opt_lg_dirty_mult) <
- arena->ndirty)
- arena_purge(arena);
-}
-
-#ifdef MALLOC_STATS
-static void
-arena_stats_print(arena_t *arena)
-{
-
- malloc_printf("dirty pages: %zu:%zu active:dirty, %"PRIu64" sweep%s,"
- " %"PRIu64" madvise%s, %"PRIu64" purged\n",
- arena->nactive, arena->ndirty,
- arena->stats.npurge, arena->stats.npurge == 1 ? "" : "s",
- arena->stats.nmadvise, arena->stats.nmadvise == 1 ? "" : "s",
- arena->stats.purged);
-
- malloc_printf(" allocated nmalloc ndalloc\n");
- malloc_printf("small: %12zu %12"PRIu64" %12"PRIu64"\n",
- arena->stats.allocated_small, arena->stats.nmalloc_small,
- arena->stats.ndalloc_small);
- malloc_printf("medium: %12zu %12"PRIu64" %12"PRIu64"\n",
- arena->stats.allocated_medium, arena->stats.nmalloc_medium,
- arena->stats.ndalloc_medium);
- malloc_printf("large: %12zu %12"PRIu64" %12"PRIu64"\n",
- arena->stats.allocated_large, arena->stats.nmalloc_large,
- arena->stats.ndalloc_large);
- malloc_printf("total: %12zu %12"PRIu64" %12"PRIu64"\n",
- arena->stats.allocated_small + arena->stats.allocated_medium +
- arena->stats.allocated_large, arena->stats.nmalloc_small +
- arena->stats.nmalloc_medium + arena->stats.nmalloc_large,
- arena->stats.ndalloc_small + arena->stats.ndalloc_medium +
- arena->stats.ndalloc_large);
- malloc_printf("mapped: %12zu\n", arena->stats.mapped);
-
- if (arena->stats.nmalloc_small + arena->stats.nmalloc_medium > 0) {
- unsigned i, gap_start;
-#ifdef MALLOC_TCACHE
- malloc_printf("bins: bin size regs pgs requests "
- "nfills nflushes newruns reruns maxruns curruns\n");
-#else
- malloc_printf("bins: bin size regs pgs requests "
- "newruns reruns maxruns curruns\n");
-#endif
- for (i = 0, gap_start = UINT_MAX; i < nbins; i++) {
- if (arena->bins[i].stats.nruns == 0) {
- if (gap_start == UINT_MAX)
- gap_start = i;
- } else {
- if (gap_start != UINT_MAX) {
- if (i > gap_start + 1) {
- /*
- * Gap of more than one size
- * class.
- */
- malloc_printf("[%u..%u]\n",
- gap_start, i - 1);
- } else {
- /* Gap of one size class. */
- malloc_printf("[%u]\n",
- gap_start);
- }
- gap_start = UINT_MAX;
- }
- malloc_printf(
- "%13u %1s %5u %4u %3u %9"PRIu64" %9"PRIu64
-#ifdef MALLOC_TCACHE
- " %9"PRIu64" %9"PRIu64
-#endif
- " %9"PRIu64" %7zu %7zu\n",
- i,
- i < ntbins ? "T" : i < ntbins + nqbins ?
- "Q" : i < ntbins + nqbins + ncbins ? "C" :
- i < ntbins + nqbins + ncbins + nsbins ? "S"
- : "M",
- arena->bins[i].reg_size,
- arena->bins[i].nregs,
- arena->bins[i].run_size >> PAGE_SHIFT,
- arena->bins[i].stats.nrequests,
-#ifdef MALLOC_TCACHE
- arena->bins[i].stats.nfills,
- arena->bins[i].stats.nflushes,
-#endif
- arena->bins[i].stats.nruns,
- arena->bins[i].stats.reruns,
- arena->bins[i].stats.highruns,
- arena->bins[i].stats.curruns);
- }
- }
- if (gap_start != UINT_MAX) {
- if (i > gap_start + 1) {
- /* Gap of more than one size class. */
- malloc_printf("[%u..%u]\n", gap_start, i - 1);
- } else {
- /* Gap of one size class. */
- malloc_printf("[%u]\n", gap_start);
- }
- }
- }
-
- if (arena->stats.nmalloc_large > 0) {
- size_t i;
- ssize_t gap_start;
- size_t nlclasses = (chunksize - PAGE_SIZE) >> PAGE_SHIFT;
-
- malloc_printf(
- "large: size pages nrequests maxruns curruns\n");
-
- for (i = 0, gap_start = -1; i < nlclasses; i++) {
- if (arena->stats.lstats[i].nrequests == 0) {
- if (gap_start == -1)
- gap_start = i;
- } else {
- if (gap_start != -1) {
- malloc_printf("[%zu]\n", i - gap_start);
- gap_start = -1;
- }
- malloc_printf(
- "%13zu %5zu %9"PRIu64" %9zu %9zu\n",
- (i+1) << PAGE_SHIFT, i+1,
- arena->stats.lstats[i].nrequests,
- arena->stats.lstats[i].highruns,
- arena->stats.lstats[i].curruns);
- }
- }
- if (gap_start != -1)
- malloc_printf("[%zu]\n", i - gap_start);
- }
-}
-#endif
-
-static void
-stats_print_atexit(void)
-{
-
-#if (defined(MALLOC_TCACHE) && defined(MALLOC_STATS))
- unsigned i;
-
- /*
- * Merge stats from extant threads. This is racy, since individual
- * threads do not lock when recording tcache stats events. As a
- * consequence, the final stats may be slightly out of date by the time
- * they are reported, if other threads continue to allocate.
- */
- for (i = 0; i < narenas; i++) {
- arena_t *arena = arenas[i];
- if (arena != NULL) {
- tcache_t *tcache;
-
- malloc_spin_lock(&arena->lock);
- ql_foreach(tcache, &arena->tcache_ql, link) {
- tcache_stats_merge(tcache, arena);
- }
- malloc_spin_unlock(&arena->lock);
- }
- }
-#endif
- malloc_stats_print();
-}
-
-#ifdef MALLOC_TCACHE
-static void
-tcache_bin_flush(tcache_bin_t *tbin, size_t binind, unsigned rem)
-{
- arena_chunk_t *chunk;
- arena_t *arena;
- void *ptr;
- unsigned i, ndeferred, ncached;
-
- for (ndeferred = tbin->ncached - rem; ndeferred > 0;) {
- ncached = ndeferred;
- /* Lock the arena associated with the first object. */
- chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(tbin->slots[0]);
- arena = chunk->arena;
- malloc_spin_lock(&arena->lock);
- /* Deallocate every object that belongs to the locked arena. */
- for (i = ndeferred = 0; i < ncached; i++) {
- ptr = tbin->slots[i];
- chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);
- if (chunk->arena == arena) {
- size_t pageind = (((uintptr_t)ptr -
- (uintptr_t)chunk) >> PAGE_SHIFT);
- arena_chunk_map_t *mapelm =
- &chunk->map[pageind];
- arena_dalloc_bin(arena, chunk, ptr, mapelm);
- } else {
- /*
- * This object was allocated via a different
- * arena than the one that is currently locked.
- * Stash the object, so that it can be handled
- * in a future pass.
- */
- tbin->slots[ndeferred] = ptr;
- ndeferred++;
- }
- }
-#ifdef MALLOC_STATS
- arena->bins[binind].stats.nflushes++;
- {
- arena_bin_t *bin = &arena->bins[binind];
- bin->stats.nrequests += tbin->tstats.nrequests;
- if (bin->reg_size <= small_maxclass) {
- arena->stats.nmalloc_small +=
- tbin->tstats.nrequests;
- } else {
- arena->stats.nmalloc_medium +=
- tbin->tstats.nrequests;
- }
- tbin->tstats.nrequests = 0;
- }
-#endif
- malloc_spin_unlock(&arena->lock);
- }
-
- if (rem > 0) {
- /*
- * Shift the remaining valid pointers to the base of the slots
- * array.
- */
- memmove(&tbin->slots[0], &tbin->slots[tbin->ncached - rem],
- rem * sizeof(void *));
- }
- tbin->ncached = rem;
-}
-
-static inline void
-tcache_dalloc(tcache_t *tcache, void *ptr)
-{
- arena_t *arena;
- arena_chunk_t *chunk;
- arena_run_t *run;
- arena_bin_t *bin;
- tcache_bin_t *tbin;
- size_t pageind, binind;
- arena_chunk_map_t *mapelm;
-
- chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);
- arena = chunk->arena;
- pageind = (((uintptr_t)ptr - (uintptr_t)chunk) >> PAGE_SHIFT);
- mapelm = &chunk->map[pageind];
- run = (arena_run_t *)((uintptr_t)chunk + (uintptr_t)((pageind -
- ((mapelm->bits & CHUNK_MAP_PG_MASK) >> CHUNK_MAP_PG_SHIFT)) <<
- PAGE_SHIFT));
- assert(run->magic == ARENA_RUN_MAGIC);
- bin = run->bin;
- binind = ((uintptr_t)bin - (uintptr_t)&arena->bins) /
- sizeof(arena_bin_t);
- assert(binind < nbins);
-
- if (opt_junk)
- memset(ptr, 0x5a, arena->bins[binind].reg_size);
-
- tbin = tcache->tbins[binind];
- if (tbin == NULL) {
- tbin = tcache_bin_create(choose_arena());
- if (tbin == NULL) {
- malloc_spin_lock(&arena->lock);
- arena_dalloc_bin(arena, chunk, ptr, mapelm);
- malloc_spin_unlock(&arena->lock);
- return;
- }
- tcache->tbins[binind] = tbin;
- }
-
- if (tbin->ncached == tcache_nslots)
- tcache_bin_flush(tbin, binind, (tcache_nslots >> 1));
- assert(tbin->ncached < tcache_nslots);
- tbin->slots[tbin->ncached] = ptr;
- tbin->ncached++;
- if (tbin->ncached > tbin->high_water)
- tbin->high_water = tbin->ncached;
-
- tcache_event(tcache);
-}
-#endif
-
-static void
-arena_dalloc_large(arena_t *arena, arena_chunk_t *chunk, void *ptr)
-{
-
- /* Large allocation. */
- malloc_spin_lock(&arena->lock);
-
-#ifndef MALLOC_STATS
- if (opt_junk)
-#endif
- {
- size_t pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >>
- PAGE_SHIFT;
- size_t size = chunk->map[pageind].bits & ~PAGE_MASK;
-
-#ifdef MALLOC_STATS
- if (opt_junk)
-#endif
- memset(ptr, 0x5a, size);
-#ifdef MALLOC_STATS
- arena->stats.ndalloc_large++;
- arena->stats.allocated_large -= size;
- arena->stats.lstats[(size >> PAGE_SHIFT) - 1].curruns--;
-#endif
- }
-
- arena_run_dalloc(arena, (arena_run_t *)ptr, true);
- malloc_spin_unlock(&arena->lock);
-}
-
-static inline void
-arena_dalloc(arena_t *arena, arena_chunk_t *chunk, void *ptr)
-{
- size_t pageind;
- arena_chunk_map_t *mapelm;
-
- assert(arena != NULL);
- assert(arena->magic == ARENA_MAGIC);
- assert(chunk->arena == arena);
- assert(ptr != NULL);
- assert(CHUNK_ADDR2BASE(ptr) != ptr);
-
- pageind = (((uintptr_t)ptr - (uintptr_t)chunk) >> PAGE_SHIFT);
- mapelm = &chunk->map[pageind];
- assert((mapelm->bits & CHUNK_MAP_ALLOCATED) != 0);
- if ((mapelm->bits & CHUNK_MAP_LARGE) == 0) {
- /* Small allocation. */
-#ifdef MALLOC_TCACHE
- if (__isthreaded && tcache_nslots) {
- tcache_t *tcache = tcache_tls;
- if ((uintptr_t)tcache > (uintptr_t)1)
- tcache_dalloc(tcache, ptr);
- else {
- arena_dalloc_hard(arena, chunk, ptr, mapelm,
- tcache);
- }
- } else {
-#endif
- malloc_spin_lock(&arena->lock);
- arena_dalloc_bin(arena, chunk, ptr, mapelm);
- malloc_spin_unlock(&arena->lock);
-#ifdef MALLOC_TCACHE
- }
-#endif
- } else
- arena_dalloc_large(arena, chunk, ptr);
-}
-
-#ifdef MALLOC_TCACHE
-static void
-arena_dalloc_hard(arena_t *arena, arena_chunk_t *chunk, void *ptr,
- arena_chunk_map_t *mapelm, tcache_t *tcache)
-{
-
- if (tcache == NULL) {
- tcache = tcache_create(arena);
- if (tcache == NULL) {
- malloc_spin_lock(&arena->lock);
- arena_dalloc_bin(arena, chunk, ptr, mapelm);
- malloc_spin_unlock(&arena->lock);
- } else
- tcache_dalloc(tcache, ptr);
- } else {
- /* This thread is currently exiting, so directly deallocate. */
- assert(tcache == (void *)(uintptr_t)1);
- malloc_spin_lock(&arena->lock);
- arena_dalloc_bin(arena, chunk, ptr, mapelm);
- malloc_spin_unlock(&arena->lock);
- }
-}
-#endif
-
-static inline void
-idalloc(void *ptr)
-{
- arena_chunk_t *chunk;
-
- assert(ptr != NULL);
-
- chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);
- if (chunk != ptr)
- arena_dalloc(chunk->arena, chunk, ptr);
- else
- huge_dalloc(ptr);
-}
-
-static void
-arena_ralloc_large_shrink(arena_t *arena, arena_chunk_t *chunk, void *ptr,
- size_t size, size_t oldsize)
-{
-
- assert(size < oldsize);
-
- /*
- * Shrink the run, and make trailing pages available for other
- * allocations.
- */
- malloc_spin_lock(&arena->lock);
- arena_run_trim_tail(arena, chunk, (arena_run_t *)ptr, oldsize, size,
- true);
-#ifdef MALLOC_STATS
- arena->stats.ndalloc_large++;
- arena->stats.allocated_large -= oldsize;
- arena->stats.lstats[(oldsize >> PAGE_SHIFT) - 1].curruns--;
-
- arena->stats.nmalloc_large++;
- arena->stats.allocated_large += size;
- arena->stats.lstats[(size >> PAGE_SHIFT) - 1].nrequests++;
- arena->stats.lstats[(size >> PAGE_SHIFT) - 1].curruns++;
- if (arena->stats.lstats[(size >> PAGE_SHIFT) - 1].curruns >
- arena->stats.lstats[(size >> PAGE_SHIFT) - 1].highruns) {
- arena->stats.lstats[(size >> PAGE_SHIFT) - 1].highruns =
- arena->stats.lstats[(size >> PAGE_SHIFT) - 1].curruns;
- }
-#endif
- malloc_spin_unlock(&arena->lock);
-}
-
-static bool
-arena_ralloc_large_grow(arena_t *arena, arena_chunk_t *chunk, void *ptr,
- size_t size, size_t oldsize)
-{
- size_t pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> PAGE_SHIFT;
- size_t npages = oldsize >> PAGE_SHIFT;
-
- assert(oldsize == (chunk->map[pageind].bits & ~PAGE_MASK));
-
- /* Try to extend the run. */
- assert(size > oldsize);
- malloc_spin_lock(&arena->lock);
- if (pageind + npages < chunk_npages && (chunk->map[pageind+npages].bits
- & CHUNK_MAP_ALLOCATED) == 0 && (chunk->map[pageind+npages].bits &
- ~PAGE_MASK) >= size - oldsize) {
- /*
- * The next run is available and sufficiently large. Split the
- * following run, then merge the first part with the existing
- * allocation.
- */
- arena_run_split(arena, (arena_run_t *)((uintptr_t)chunk +
- ((pageind+npages) << PAGE_SHIFT)), size - oldsize, true,
- false);
-
- chunk->map[pageind].bits = size | CHUNK_MAP_LARGE |
- CHUNK_MAP_ALLOCATED;
- chunk->map[pageind+npages].bits = CHUNK_MAP_LARGE |
- CHUNK_MAP_ALLOCATED;
-
-#ifdef MALLOC_STATS
- arena->stats.ndalloc_large++;
- arena->stats.allocated_large -= oldsize;
- arena->stats.lstats[(oldsize >> PAGE_SHIFT) - 1].curruns--;
-
- arena->stats.nmalloc_large++;
- arena->stats.allocated_large += size;
- arena->stats.lstats[(size >> PAGE_SHIFT) - 1].nrequests++;
- arena->stats.lstats[(size >> PAGE_SHIFT) - 1].curruns++;
- if (arena->stats.lstats[(size >> PAGE_SHIFT) - 1].curruns >
- arena->stats.lstats[(size >> PAGE_SHIFT) - 1].highruns) {
- arena->stats.lstats[(size >> PAGE_SHIFT) - 1].highruns =
- arena->stats.lstats[(size >> PAGE_SHIFT) - 1].curruns;
- }
-#endif
- malloc_spin_unlock(&arena->lock);
- return (false);
- }
- malloc_spin_unlock(&arena->lock);
-
- return (true);
-}
-
-/*
- * Try to resize a large allocation, in order to avoid copying. This will
- * always fail if growing an object, and the following run is already in use.
- */
-static bool
-arena_ralloc_large(void *ptr, size_t size, size_t oldsize)
-{
- size_t psize;
-
- psize = PAGE_CEILING(size);
- if (psize == oldsize) {
- /* Same size class. */
- if (opt_junk && size < oldsize) {
- memset((void *)((uintptr_t)ptr + size), 0x5a, oldsize -
- size);
- }
- return (false);
- } else {
- arena_chunk_t *chunk;
- arena_t *arena;
-
- chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);
- arena = chunk->arena;
- assert(arena->magic == ARENA_MAGIC);
-
- if (psize < oldsize) {
- /* Fill before shrinking in order avoid a race. */
- if (opt_junk) {
- memset((void *)((uintptr_t)ptr + size), 0x5a,
- oldsize - size);
- }
- arena_ralloc_large_shrink(arena, chunk, ptr, psize,
- oldsize);
- return (false);
- } else {
- bool ret = arena_ralloc_large_grow(arena, chunk, ptr,
- psize, oldsize);
- if (ret == false && opt_zero) {
- memset((void *)((uintptr_t)ptr + oldsize), 0,
- size - oldsize);
- }
- return (ret);
- }
- }
-}
-
-static void *
-arena_ralloc(void *ptr, size_t size, size_t oldsize)
-{
- void *ret;
- size_t copysize;
-
- /*
- * Try to avoid moving the allocation.
- *
- * posix_memalign() can cause allocation of "large" objects that are
- * smaller than bin_maxclass (in order to meet alignment requirements).
- * Therefore, do not assume that (oldsize <= bin_maxclass) indicates
- * ptr refers to a bin-allocated object.
- */
- if (oldsize <= arena_maxclass) {
- if (arena_is_large(ptr) == false ) {
- if (size <= small_maxclass) {
- if (oldsize <= small_maxclass &&
- small_size2bin[size] ==
- small_size2bin[oldsize])
- goto IN_PLACE;
- } else if (size <= bin_maxclass) {
- if (small_maxclass < oldsize && oldsize <=
- bin_maxclass && MEDIUM_CEILING(size) ==
- MEDIUM_CEILING(oldsize))
- goto IN_PLACE;
- }
- } else {
- assert(size <= arena_maxclass);
- if (size > bin_maxclass) {
- if (arena_ralloc_large(ptr, size, oldsize) ==
- false)
- return (ptr);
- }
- }
- }
-
- /* Try to avoid moving the allocation. */
- if (size <= small_maxclass) {
- if (oldsize <= small_maxclass && small_size2bin[size] ==
- small_size2bin[oldsize])
- goto IN_PLACE;
- } else if (size <= bin_maxclass) {
- if (small_maxclass < oldsize && oldsize <= bin_maxclass &&
- MEDIUM_CEILING(size) == MEDIUM_CEILING(oldsize))
- goto IN_PLACE;
- } else {
- if (bin_maxclass < oldsize && oldsize <= arena_maxclass) {
- assert(size > bin_maxclass);
- if (arena_ralloc_large(ptr, size, oldsize) == false)
- return (ptr);
- }
- }
-
- /*
- * If we get here, then size and oldsize are different enough that we
- * need to move the object. In that case, fall back to allocating new
- * space and copying.
- */
- ret = arena_malloc(size, false);
- if (ret == NULL)
- return (NULL);
-
- /* Junk/zero-filling were already done by arena_malloc(). */
- copysize = (size < oldsize) ? size : oldsize;
- memcpy(ret, ptr, copysize);
- idalloc(ptr);
- return (ret);
-IN_PLACE:
- if (opt_junk && size < oldsize)
- memset((void *)((uintptr_t)ptr + size), 0x5a, oldsize - size);
- else if (opt_zero && size > oldsize)
- memset((void *)((uintptr_t)ptr + oldsize), 0, size - oldsize);
- return (ptr);
-}
-
-static inline void *
-iralloc(void *ptr, size_t size)
-{
- size_t oldsize;
-
- assert(ptr != NULL);
- assert(size != 0);
-
- oldsize = isalloc(ptr);
-
- if (size <= arena_maxclass)
- return (arena_ralloc(ptr, size, oldsize));
- else
- return (huge_ralloc(ptr, size, oldsize));
-}
-
-static bool
-arena_new(arena_t *arena, unsigned ind)
-{
- unsigned i;
- arena_bin_t *bin;
- size_t prev_run_size;
-
- if (malloc_spin_init(&arena->lock))
- return (true);
-
-#ifdef MALLOC_STATS
- memset(&arena->stats, 0, sizeof(arena_stats_t));
- arena->stats.lstats = (malloc_large_stats_t *)base_alloc(
- sizeof(malloc_large_stats_t) * ((chunksize - PAGE_SIZE) >>
- PAGE_SHIFT));
- if (arena->stats.lstats == NULL)
- return (true);
- memset(arena->stats.lstats, 0, sizeof(malloc_large_stats_t) *
- ((chunksize - PAGE_SIZE) >> PAGE_SHIFT));
-# ifdef MALLOC_TCACHE
- ql_new(&arena->tcache_ql);
-# endif
-#endif
-
- /* Initialize chunks. */
- arena_chunk_tree_dirty_new(&arena->chunks_dirty);
- arena->spare = NULL;
-
- arena->nactive = 0;
- arena->ndirty = 0;
-
- arena_avail_tree_new(&arena->runs_avail);
-
- /* Initialize bins. */
- prev_run_size = PAGE_SIZE;
-
- i = 0;
-#ifdef MALLOC_TINY
- /* (2^n)-spaced tiny bins. */
- for (; i < ntbins; i++) {
- bin = &arena->bins[i];
- bin->runcur = NULL;
- arena_run_tree_new(&bin->runs);
-
- bin->reg_size = (1U << (LG_TINY_MIN + i));
-
- prev_run_size = arena_bin_run_size_calc(bin, prev_run_size);
-
-#ifdef MALLOC_STATS
- memset(&bin->stats, 0, sizeof(malloc_bin_stats_t));
-#endif
- }
-#endif
-
- /* Quantum-spaced bins. */
- for (; i < ntbins + nqbins; i++) {
- bin = &arena->bins[i];
- bin->runcur = NULL;
- arena_run_tree_new(&bin->runs);
-
- bin->reg_size = (i - ntbins + 1) << LG_QUANTUM;
-
- prev_run_size = arena_bin_run_size_calc(bin, prev_run_size);
-
-#ifdef MALLOC_STATS
- memset(&bin->stats, 0, sizeof(malloc_bin_stats_t));
-#endif
- }
-
- /* Cacheline-spaced bins. */
- for (; i < ntbins + nqbins + ncbins; i++) {
- bin = &arena->bins[i];
- bin->runcur = NULL;
- arena_run_tree_new(&bin->runs);
-
- bin->reg_size = cspace_min + ((i - (ntbins + nqbins)) <<
- LG_CACHELINE);
-
- prev_run_size = arena_bin_run_size_calc(bin, prev_run_size);
-
-#ifdef MALLOC_STATS
- memset(&bin->stats, 0, sizeof(malloc_bin_stats_t));
-#endif
- }
-
- /* Subpage-spaced bins. */
- for (; i < ntbins + nqbins + ncbins + nsbins; i++) {
- bin = &arena->bins[i];
- bin->runcur = NULL;
- arena_run_tree_new(&bin->runs);
-
- bin->reg_size = sspace_min + ((i - (ntbins + nqbins + ncbins))
- << LG_SUBPAGE);
-
- prev_run_size = arena_bin_run_size_calc(bin, prev_run_size);
-
-#ifdef MALLOC_STATS
- memset(&bin->stats, 0, sizeof(malloc_bin_stats_t));
-#endif
- }
-
- /* Medium bins. */
- for (; i < nbins; i++) {
- bin = &arena->bins[i];
- bin->runcur = NULL;
- arena_run_tree_new(&bin->runs);
-
- bin->reg_size = medium_min + ((i - (ntbins + nqbins + ncbins +
- nsbins)) << lg_mspace);
-
- prev_run_size = arena_bin_run_size_calc(bin, prev_run_size);
-
-#ifdef MALLOC_STATS
- memset(&bin->stats, 0, sizeof(malloc_bin_stats_t));
-#endif
- }
-
-#ifdef MALLOC_DEBUG
- arena->magic = ARENA_MAGIC;
-#endif
-
- return (false);
-}
-
-/* Create a new arena and insert it into the arenas array at index ind. */
-static arena_t *
-arenas_extend(unsigned ind)
-{
- arena_t *ret;
-
- /* Allocate enough space for trailing bins. */
- ret = (arena_t *)base_alloc(sizeof(arena_t)
- + (sizeof(arena_bin_t) * (nbins - 1)));
- if (ret != NULL && arena_new(ret, ind) == false) {
- arenas[ind] = ret;
- return (ret);
- }
- /* Only reached if there is an OOM error. */
-
- /*
- * OOM here is quite inconvenient to propagate, since dealing with it
- * would require a check for failure in the fast path. Instead, punt
- * by using arenas[0]. In practice, this is an extremely unlikely
- * failure.
- */
- _malloc_message(_getprogname(),
- ": (malloc) Error initializing arena\n", "", "");
- if (opt_abort)
- abort();
-
- return (arenas[0]);
-}
-
-#ifdef MALLOC_TCACHE
-static tcache_bin_t *
-tcache_bin_create(arena_t *arena)
-{
- tcache_bin_t *ret;
- size_t tsize;
-
- tsize = sizeof(tcache_bin_t) + (sizeof(void *) * (tcache_nslots - 1));
- if (tsize <= small_maxclass)
- ret = (tcache_bin_t *)arena_malloc_small(arena, tsize, false);
- else if (tsize <= bin_maxclass)
- ret = (tcache_bin_t *)arena_malloc_medium(arena, tsize, false);
- else
- ret = (tcache_bin_t *)imalloc(tsize);
- if (ret == NULL)
- return (NULL);
-#ifdef MALLOC_STATS
- memset(&ret->tstats, 0, sizeof(tcache_bin_stats_t));
-#endif
- ret->low_water = 0;
- ret->high_water = 0;
- ret->ncached = 0;
-
- return (ret);
-}
-
-static void
-tcache_bin_destroy(tcache_t *tcache, tcache_bin_t *tbin, unsigned binind)
-{
- arena_t *arena;
- arena_chunk_t *chunk;
- size_t pageind, tsize;
- arena_chunk_map_t *mapelm;
-
- chunk = CHUNK_ADDR2BASE(tbin);
- arena = chunk->arena;
- pageind = (((uintptr_t)tbin - (uintptr_t)chunk) >> PAGE_SHIFT);
- mapelm = &chunk->map[pageind];
-
-#ifdef MALLOC_STATS
- if (tbin->tstats.nrequests != 0) {
- arena_t *arena = tcache->arena;
- arena_bin_t *bin = &arena->bins[binind];
- malloc_spin_lock(&arena->lock);
- bin->stats.nrequests += tbin->tstats.nrequests;
- if (bin->reg_size <= small_maxclass)
- arena->stats.nmalloc_small += tbin->tstats.nrequests;
- else
- arena->stats.nmalloc_medium += tbin->tstats.nrequests;
- malloc_spin_unlock(&arena->lock);
- }
-#endif
-
- assert(tbin->ncached == 0);
- tsize = sizeof(tcache_bin_t) + (sizeof(void *) * (tcache_nslots - 1));
- if (tsize <= bin_maxclass) {
- malloc_spin_lock(&arena->lock);
- arena_dalloc_bin(arena, chunk, tbin, mapelm);
- malloc_spin_unlock(&arena->lock);
- } else
- idalloc(tbin);
-}
-
-#ifdef MALLOC_STATS
-static void
-tcache_stats_merge(tcache_t *tcache, arena_t *arena)
-{
- unsigned i;
-
- /* Merge and reset tcache stats. */
- for (i = 0; i < mbin0; i++) {
- arena_bin_t *bin = &arena->bins[i];
- tcache_bin_t *tbin = tcache->tbins[i];
- if (tbin != NULL) {
- bin->stats.nrequests += tbin->tstats.nrequests;
- arena->stats.nmalloc_small += tbin->tstats.nrequests;
- tbin->tstats.nrequests = 0;
- }
- }
- for (; i < nbins; i++) {
- arena_bin_t *bin = &arena->bins[i];
- tcache_bin_t *tbin = tcache->tbins[i];
- if (tbin != NULL) {
- bin->stats.nrequests += tbin->tstats.nrequests;
- arena->stats.nmalloc_medium += tbin->tstats.nrequests;
- tbin->tstats.nrequests = 0;
- }
- }
-}
-#endif
-
-static tcache_t *
-tcache_create(arena_t *arena)
-{
- tcache_t *tcache;
-
- if (sizeof(tcache_t) + (sizeof(tcache_bin_t *) * (nbins - 1)) <=
- small_maxclass) {
- tcache = (tcache_t *)arena_malloc_small(arena, sizeof(tcache_t)
- + (sizeof(tcache_bin_t *) * (nbins - 1)), true);
- } else if (sizeof(tcache_t) + (sizeof(tcache_bin_t *) * (nbins - 1)) <=
- bin_maxclass) {
- tcache = (tcache_t *)arena_malloc_medium(arena, sizeof(tcache_t)
- + (sizeof(tcache_bin_t *) * (nbins - 1)), true);
- } else {
- tcache = (tcache_t *)icalloc(sizeof(tcache_t) +
- (sizeof(tcache_bin_t *) * (nbins - 1)));
- }
-
- if (tcache == NULL)
- return (NULL);
-
-#ifdef MALLOC_STATS
- /* Link into list of extant tcaches. */
- malloc_spin_lock(&arena->lock);
- ql_elm_new(tcache, link);
- ql_tail_insert(&arena->tcache_ql, tcache, link);
- malloc_spin_unlock(&arena->lock);
-#endif
-
- tcache->arena = arena;
-
- tcache_tls = tcache;
-
- return (tcache);
-}
-
-static void
-tcache_destroy(tcache_t *tcache)
-{
- unsigned i;
-
-#ifdef MALLOC_STATS
- /* Unlink from list of extant tcaches. */
- malloc_spin_lock(&tcache->arena->lock);
- ql_remove(&tcache->arena->tcache_ql, tcache, link);
- tcache_stats_merge(tcache, tcache->arena);
- malloc_spin_unlock(&tcache->arena->lock);
-#endif
-
- for (i = 0; i < nbins; i++) {
- tcache_bin_t *tbin = tcache->tbins[i];
- if (tbin != NULL) {
- tcache_bin_flush(tbin, i, 0);
- tcache_bin_destroy(tcache, tbin, i);
- }
- }
-
- if (arena_salloc(tcache) <= bin_maxclass) {
- arena_chunk_t *chunk = CHUNK_ADDR2BASE(tcache);
- arena_t *arena = chunk->arena;
- size_t pageind = (((uintptr_t)tcache - (uintptr_t)chunk) >>
- PAGE_SHIFT);
- arena_chunk_map_t *mapelm = &chunk->map[pageind];
-
- malloc_spin_lock(&arena->lock);
- arena_dalloc_bin(arena, chunk, tcache, mapelm);
- malloc_spin_unlock(&arena->lock);
- } else
- idalloc(tcache);
-}
-#endif
-
-/*
- * End arena.
- */
-/******************************************************************************/
-/*
- * Begin general internal functions.
- */
-
-static void *
-huge_malloc(size_t size, bool zero)
-{
- void *ret;
- size_t csize;
- extent_node_t *node;
-
- /* Allocate one or more contiguous chunks for this request. */
-
- csize = CHUNK_CEILING(size);
- if (csize == 0) {
- /* size is large enough to cause size_t wrap-around. */
- return (NULL);
- }
-
- /* Allocate an extent node with which to track the chunk. */
- node = base_node_alloc();
- if (node == NULL)
- return (NULL);
-
- ret = chunk_alloc(csize, &zero);
- if (ret == NULL) {
- base_node_dealloc(node);
- return (NULL);
- }
-
- /* Insert node into huge. */
- node->addr = ret;
- node->size = csize;
-
- malloc_mutex_lock(&huge_mtx);
- extent_tree_ad_insert(&huge, node);
-#ifdef MALLOC_STATS
- huge_nmalloc++;
- huge_allocated += csize;
-#endif
- malloc_mutex_unlock(&huge_mtx);
-
- if (zero == false) {
- if (opt_junk)
- memset(ret, 0xa5, csize);
- else if (opt_zero)
- memset(ret, 0, csize);
- }
-
- return (ret);
-}
-
-/* Only handles large allocations that require more than chunk alignment. */
-static void *
-huge_palloc(size_t alignment, size_t size)
-{
- void *ret;
- size_t alloc_size, chunk_size, offset;
- extent_node_t *node;
- bool zero;
-
- /*
- * This allocation requires alignment that is even larger than chunk
- * alignment. This means that huge_malloc() isn't good enough.
- *
- * Allocate almost twice as many chunks as are demanded by the size or
- * alignment, in order to assure the alignment can be achieved, then
- * unmap leading and trailing chunks.
- */
- assert(alignment >= chunksize);
-
- chunk_size = CHUNK_CEILING(size);
-
- if (size >= alignment)
- alloc_size = chunk_size + alignment - chunksize;
- else
- alloc_size = (alignment << 1) - chunksize;
-
- /* Allocate an extent node with which to track the chunk. */
- node = base_node_alloc();
- if (node == NULL)
- return (NULL);
-
- zero = false;
- ret = chunk_alloc(alloc_size, &zero);
- if (ret == NULL) {
- base_node_dealloc(node);
- return (NULL);
- }
-
- offset = (uintptr_t)ret & (alignment - 1);
- assert((offset & chunksize_mask) == 0);
- assert(offset < alloc_size);
- if (offset == 0) {
- /* Trim trailing space. */
- chunk_dealloc((void *)((uintptr_t)ret + chunk_size), alloc_size
- - chunk_size);
- } else {
- size_t trailsize;
-
- /* Trim leading space. */
- chunk_dealloc(ret, alignment - offset);
-
- ret = (void *)((uintptr_t)ret + (alignment - offset));
-
- trailsize = alloc_size - (alignment - offset) - chunk_size;
- if (trailsize != 0) {
- /* Trim trailing space. */
- assert(trailsize < alloc_size);
- chunk_dealloc((void *)((uintptr_t)ret + chunk_size),
- trailsize);
- }
- }
-
- /* Insert node into huge. */
- node->addr = ret;
- node->size = chunk_size;
-
- malloc_mutex_lock(&huge_mtx);
- extent_tree_ad_insert(&huge, node);
-#ifdef MALLOC_STATS
- huge_nmalloc++;
- huge_allocated += chunk_size;
-#endif
- malloc_mutex_unlock(&huge_mtx);
-
- if (opt_junk)
- memset(ret, 0xa5, chunk_size);
- else if (opt_zero)
- memset(ret, 0, chunk_size);
-
- return (ret);
-}
-
-static void *
-huge_ralloc(void *ptr, size_t size, size_t oldsize)
-{
- void *ret;
- size_t copysize;
-
- /* Avoid moving the allocation if the size class would not change. */
- if (oldsize > arena_maxclass &&
- CHUNK_CEILING(size) == CHUNK_CEILING(oldsize)) {
- if (opt_junk && size < oldsize) {
- memset((void *)((uintptr_t)ptr + size), 0x5a, oldsize
- - size);
- } else if (opt_zero && size > oldsize) {
- memset((void *)((uintptr_t)ptr + oldsize), 0, size
- - oldsize);
- }
- return (ptr);
- }
-
- /*
- * If we get here, then size and oldsize are different enough that we
- * need to use a different size class. In that case, fall back to
- * allocating new space and copying.
- */
- ret = huge_malloc(size, false);
- if (ret == NULL)
- return (NULL);
-
- copysize = (size < oldsize) ? size : oldsize;
- memcpy(ret, ptr, copysize);
- idalloc(ptr);
- return (ret);
-}
-
-static void
-huge_dalloc(void *ptr)
-{
- extent_node_t *node, key;
-
- malloc_mutex_lock(&huge_mtx);
-
- /* Extract from tree of huge allocations. */
- key.addr = ptr;
- node = extent_tree_ad_search(&huge, &key);
- assert(node != NULL);
- assert(node->addr == ptr);
- extent_tree_ad_remove(&huge, node);
-
-#ifdef MALLOC_STATS
- huge_ndalloc++;
- huge_allocated -= node->size;
-#endif
-
- malloc_mutex_unlock(&huge_mtx);
-
- /* Unmap chunk. */
-#ifdef MALLOC_DSS
- if (opt_dss && opt_junk)
- memset(node->addr, 0x5a, node->size);
-#endif
- chunk_dealloc(node->addr, node->size);
-
- base_node_dealloc(node);
-}
-
-static void
-malloc_stats_print(void)
-{
- char s[UMAX2S_BUFSIZE];
-
- _malloc_message("___ Begin malloc statistics ___\n", "", "", "");
- _malloc_message("Assertions ",
-#ifdef NDEBUG
- "disabled",
-#else
- "enabled",
-#endif
- "\n", "");
- _malloc_message("Boolean MALLOC_OPTIONS: ", opt_abort ? "A" : "a", "", "");
-#ifdef MALLOC_DSS
- _malloc_message(opt_dss ? "D" : "d", "", "", "");
-#endif
- _malloc_message(opt_junk ? "J" : "j", "", "", "");
-#ifdef MALLOC_DSS
- _malloc_message(opt_mmap ? "M" : "m", "", "", "");
-#endif
- _malloc_message("P", "", "", "");
- _malloc_message(opt_utrace ? "U" : "u", "", "", "");
- _malloc_message(opt_sysv ? "V" : "v", "", "", "");
- _malloc_message(opt_xmalloc ? "X" : "x", "", "", "");
- _malloc_message(opt_zero ? "Z" : "z", "", "", "");
- _malloc_message("\n", "", "", "");
-
- _malloc_message("CPUs: ", umax2s(ncpus, 10, s), "\n", "");
- _malloc_message("Max arenas: ", umax2s(narenas, 10, s), "\n", "");
- _malloc_message("Pointer size: ", umax2s(sizeof(void *), 10, s), "\n", "");
- _malloc_message("Quantum size: ", umax2s(QUANTUM, 10, s), "\n", "");
- _malloc_message("Cacheline size (assumed): ",
- umax2s(CACHELINE, 10, s), "\n", "");
- _malloc_message("Subpage spacing: ", umax2s(SUBPAGE, 10, s), "\n", "");
- _malloc_message("Medium spacing: ", umax2s((1U << lg_mspace), 10, s), "\n",
- "");
-#ifdef MALLOC_TINY
- _malloc_message("Tiny 2^n-spaced sizes: [", umax2s((1U << LG_TINY_MIN), 10,
- s), "..", "");
- _malloc_message(umax2s((qspace_min >> 1), 10, s), "]\n", "", "");
-#endif
- _malloc_message("Quantum-spaced sizes: [", umax2s(qspace_min, 10, s), "..",
- "");
- _malloc_message(umax2s(qspace_max, 10, s), "]\n", "", "");
- _malloc_message("Cacheline-spaced sizes: [",
- umax2s(cspace_min, 10, s), "..", "");
- _malloc_message(umax2s(cspace_max, 10, s), "]\n", "", "");
- _malloc_message("Subpage-spaced sizes: [", umax2s(sspace_min, 10, s), "..",
- "");
- _malloc_message(umax2s(sspace_max, 10, s), "]\n", "", "");
- _malloc_message("Medium sizes: [", umax2s(medium_min, 10, s), "..", "");
- _malloc_message(umax2s(medium_max, 10, s), "]\n", "", "");
- if (opt_lg_dirty_mult >= 0) {
- _malloc_message("Min active:dirty page ratio per arena: ",
- umax2s((1U << opt_lg_dirty_mult), 10, s), ":1\n", "");
- } else {
- _malloc_message("Min active:dirty page ratio per arena: N/A\n", "",
- "", "");
- }
-#ifdef MALLOC_TCACHE
- _malloc_message("Thread cache slots per size class: ",
- tcache_nslots ? umax2s(tcache_nslots, 10, s) : "N/A", "\n", "");
- _malloc_message("Thread cache GC sweep interval: ",
- (tcache_nslots && tcache_gc_incr > 0) ?
- umax2s((1U << opt_lg_tcache_gc_sweep), 10, s) : "N/A", "", "");
- _malloc_message(" (increment interval: ",
- (tcache_nslots && tcache_gc_incr > 0) ? umax2s(tcache_gc_incr, 10, s)
- : "N/A", ")\n", "");
-#endif
- _malloc_message("Chunk size: ", umax2s(chunksize, 10, s), "", "");
- _malloc_message(" (2^", umax2s(opt_lg_chunk, 10, s), ")\n", "");
-
-#ifdef MALLOC_STATS
- {
- size_t allocated, mapped;
- unsigned i;
- arena_t *arena;
-
- /* Calculate and print allocated/mapped stats. */
-
- /* arenas. */
- for (i = 0, allocated = 0; i < narenas; i++) {
- if (arenas[i] != NULL) {
- malloc_spin_lock(&arenas[i]->lock);
- allocated += arenas[i]->stats.allocated_small;
- allocated += arenas[i]->stats.allocated_large;
- malloc_spin_unlock(&arenas[i]->lock);
- }
- }
-
- /* huge/base. */
- malloc_mutex_lock(&huge_mtx);
- allocated += huge_allocated;
- mapped = stats_chunks.curchunks * chunksize;
- malloc_mutex_unlock(&huge_mtx);
-
- malloc_mutex_lock(&base_mtx);
- mapped += base_mapped;
- malloc_mutex_unlock(&base_mtx);
-
- malloc_printf("Allocated: %zu, mapped: %zu\n", allocated,
- mapped);
-
- /* Print chunk stats. */
- {
- chunk_stats_t chunks_stats;
-
- malloc_mutex_lock(&huge_mtx);
- chunks_stats = stats_chunks;
- malloc_mutex_unlock(&huge_mtx);
-
- malloc_printf("chunks: nchunks "
- "highchunks curchunks\n");
- malloc_printf(" %13"PRIu64"%13zu%13zu\n",
- chunks_stats.nchunks, chunks_stats.highchunks,
- chunks_stats.curchunks);
- }
-
- /* Print chunk stats. */
- malloc_printf(
- "huge: nmalloc ndalloc allocated\n");
- malloc_printf(" %12"PRIu64" %12"PRIu64" %12zu\n", huge_nmalloc,
- huge_ndalloc, huge_allocated);
-
- /* Print stats for each arena. */
- for (i = 0; i < narenas; i++) {
- arena = arenas[i];
- if (arena != NULL) {
- malloc_printf("\narenas[%u]:\n", i);
- malloc_spin_lock(&arena->lock);
- arena_stats_print(arena);
- malloc_spin_unlock(&arena->lock);
- }
- }
- }
-#endif /* #ifdef MALLOC_STATS */
- _malloc_message("--- End malloc statistics ---\n", "", "", "");
-}
-
-#ifdef MALLOC_DEBUG
-static void
-small_size2bin_validate(void)
-{
- size_t i, size, binind;
-
- assert(small_size2bin[0] == 0xffU);
- i = 1;
-# ifdef MALLOC_TINY
- /* Tiny. */
- for (; i < (1U << LG_TINY_MIN); i++) {
- size = pow2_ceil(1U << LG_TINY_MIN);
- binind = ffs((int)(size >> (LG_TINY_MIN + 1)));
- assert(small_size2bin[i] == binind);
- }
- for (; i < qspace_min; i++) {
- size = pow2_ceil(i);
- binind = ffs((int)(size >> (LG_TINY_MIN + 1)));
- assert(small_size2bin[i] == binind);
- }
-# endif
- /* Quantum-spaced. */
- for (; i <= qspace_max; i++) {
- size = QUANTUM_CEILING(i);
- binind = ntbins + (size >> LG_QUANTUM) - 1;
- assert(small_size2bin[i] == binind);
- }
- /* Cacheline-spaced. */
- for (; i <= cspace_max; i++) {
- size = CACHELINE_CEILING(i);
- binind = ntbins + nqbins + ((size - cspace_min) >>
- LG_CACHELINE);
- assert(small_size2bin[i] == binind);
- }
- /* Sub-page. */
- for (; i <= sspace_max; i++) {
- size = SUBPAGE_CEILING(i);
- binind = ntbins + nqbins + ncbins + ((size - sspace_min)
- >> LG_SUBPAGE);
- assert(small_size2bin[i] == binind);
- }
-}
-#endif
-
-static bool
-small_size2bin_init(void)
-{
-
- if (opt_lg_qspace_max != LG_QSPACE_MAX_DEFAULT
- || opt_lg_cspace_max != LG_CSPACE_MAX_DEFAULT
- || sizeof(const_small_size2bin) != small_maxclass + 1)
- return (small_size2bin_init_hard());
-
- small_size2bin = const_small_size2bin;
-#ifdef MALLOC_DEBUG
- assert(sizeof(const_small_size2bin) == small_maxclass + 1);
- small_size2bin_validate();
-#endif
- return (false);
-}
-
-static bool
-small_size2bin_init_hard(void)
-{
- size_t i, size, binind;
- uint8_t *custom_small_size2bin;
-
- assert(opt_lg_qspace_max != LG_QSPACE_MAX_DEFAULT
- || opt_lg_cspace_max != LG_CSPACE_MAX_DEFAULT
- || sizeof(const_small_size2bin) != small_maxclass + 1);
-
- custom_small_size2bin = (uint8_t *)base_alloc(small_maxclass + 1);
- if (custom_small_size2bin == NULL)
- return (true);
-
- custom_small_size2bin[0] = 0xffU;
- i = 1;
-#ifdef MALLOC_TINY
- /* Tiny. */
- for (; i < (1U << LG_TINY_MIN); i++) {
- size = pow2_ceil(1U << LG_TINY_MIN);
- binind = ffs((int)(size >> (LG_TINY_MIN + 1)));
- custom_small_size2bin[i] = binind;
- }
- for (; i < qspace_min; i++) {
- size = pow2_ceil(i);
- binind = ffs((int)(size >> (LG_TINY_MIN + 1)));
- custom_small_size2bin[i] = binind;
- }
-#endif
- /* Quantum-spaced. */
- for (; i <= qspace_max; i++) {
- size = QUANTUM_CEILING(i);
- binind = ntbins + (size >> LG_QUANTUM) - 1;
- custom_small_size2bin[i] = binind;
- }
- /* Cacheline-spaced. */
- for (; i <= cspace_max; i++) {
- size = CACHELINE_CEILING(i);
- binind = ntbins + nqbins + ((size - cspace_min) >>
- LG_CACHELINE);
- custom_small_size2bin[i] = binind;
- }
- /* Sub-page. */
- for (; i <= sspace_max; i++) {
- size = SUBPAGE_CEILING(i);
- binind = ntbins + nqbins + ncbins + ((size - sspace_min) >>
- LG_SUBPAGE);
- custom_small_size2bin[i] = binind;
- }
-
- small_size2bin = custom_small_size2bin;
-#ifdef MALLOC_DEBUG
- small_size2bin_validate();
-#endif
- return (false);
-}
-
-static unsigned
-malloc_ncpus(void)
-{
- int mib[2];
- unsigned ret;
- int error;
- size_t len;
-
- error = _elf_aux_info(AT_NCPUS, &ret, sizeof(ret));
- if (error != 0 || ret == 0) {
- mib[0] = CTL_HW;
- mib[1] = HW_NCPU;
- len = sizeof(ret);
- if (sysctl(mib, 2, &ret, &len, (void *)NULL, 0) == -1) {
- /* Error. */
- ret = 1;
- }
- }
-
- return (ret);
-}
-
-/*
- * FreeBSD's pthreads implementation calls malloc(3), so the malloc
- * implementation has to take pains to avoid infinite recursion during
- * initialization.
- */
-static inline bool
-malloc_init(void)
-{
-
- if (malloc_initialized == false)
- return (malloc_init_hard());
-
- return (false);
-}
-
-static bool
-malloc_init_hard(void)
-{
- unsigned i;
- int linklen;
- char buf[PATH_MAX + 1];
- const char *opts;
-
- malloc_mutex_lock(&init_lock);
- if (malloc_initialized) {
- /*
- * Another thread initialized the allocator before this one
- * acquired init_lock.
- */
- malloc_mutex_unlock(&init_lock);
- return (false);
- }
-
- /* Get number of CPUs. */
- ncpus = malloc_ncpus();
-
- /*
- * Increase the chunk size to the largest page size that is greater
- * than the default chunk size and less than or equal to 4MB.
- */
- {
- size_t pagesizes[MAXPAGESIZES];
- int k, nsizes;
-
- nsizes = getpagesizes(pagesizes, MAXPAGESIZES);
- for (k = 0; k < nsizes; k++)
- if (pagesizes[k] <= (1LU << 22))
- while ((1LU << opt_lg_chunk) < pagesizes[k])
- opt_lg_chunk++;
- }
-
- for (i = 0; i < 3; i++) {
- unsigned j;
-
- /* Get runtime configuration. */
- switch (i) {
- case 0:
- if ((linklen = readlink("/etc/malloc.conf", buf,
- sizeof(buf) - 1)) != -1) {
- /*
- * Use the contents of the "/etc/malloc.conf"
- * symbolic link's name.
- */
- buf[linklen] = '\0';
- opts = buf;
- } else {
- /* No configuration specified. */
- buf[0] = '\0';
- opts = buf;
- }
- break;
- case 1:
- if (issetugid() == 0 && (opts =
- getenv("MALLOC_OPTIONS")) != NULL) {
- /*
- * Do nothing; opts is already initialized to
- * the value of the MALLOC_OPTIONS environment
- * variable.
- */
- } else {
- /* No configuration specified. */
- buf[0] = '\0';
- opts = buf;
- }
- break;
- case 2:
- if (_malloc_options != NULL) {
- /*
- * Use options that were compiled into the
- * program.
- */
- opts = _malloc_options;
- } else {
- /* No configuration specified. */
- buf[0] = '\0';
- opts = buf;
- }
- break;
- default:
- /* NOTREACHED */
- assert(false);
- buf[0] = '\0';
- opts = buf;
- }
-
- for (j = 0; opts[j] != '\0'; j++) {
- unsigned k, nreps;
- bool nseen;
-
- /* Parse repetition count, if any. */
- for (nreps = 0, nseen = false;; j++, nseen = true) {
- switch (opts[j]) {
- case '0': case '1': case '2': case '3':
- case '4': case '5': case '6': case '7':
- case '8': case '9':
- nreps *= 10;
- nreps += opts[j] - '0';
- break;
- default:
- goto MALLOC_OUT;
- }
- }
-MALLOC_OUT:
- if (nseen == false)
- nreps = 1;
-
- for (k = 0; k < nreps; k++) {
- switch (opts[j]) {
- case 'a':
- opt_abort = false;
- break;
- case 'A':
- opt_abort = true;
- break;
- case 'c':
- if (opt_lg_cspace_max - 1 >
- opt_lg_qspace_max &&
- opt_lg_cspace_max >
- LG_CACHELINE)
- opt_lg_cspace_max--;
- break;
- case 'C':
- if (opt_lg_cspace_max < PAGE_SHIFT
- - 1)
- opt_lg_cspace_max++;
- break;
- case 'd':
-#ifdef MALLOC_DSS
- opt_dss = false;
-#endif
- break;
- case 'D':
-#ifdef MALLOC_DSS
- opt_dss = true;
-#endif
- break;
- case 'e':
- if (opt_lg_medium_max > PAGE_SHIFT)
- opt_lg_medium_max--;
- break;
- case 'E':
- if (opt_lg_medium_max + 1 <
- opt_lg_chunk)
- opt_lg_medium_max++;
- break;
- case 'f':
- if (opt_lg_dirty_mult + 1 <
- (sizeof(size_t) << 3))
- opt_lg_dirty_mult++;
- break;
- case 'F':
- if (opt_lg_dirty_mult >= 0)
- opt_lg_dirty_mult--;
- break;
-#ifdef MALLOC_TCACHE
- case 'g':
- if (opt_lg_tcache_gc_sweep >= 0)
- opt_lg_tcache_gc_sweep--;
- break;
- case 'G':
- if (opt_lg_tcache_gc_sweep + 1 <
- (sizeof(size_t) << 3))
- opt_lg_tcache_gc_sweep++;
- break;
- case 'h':
- if (opt_lg_tcache_nslots > 0)
- opt_lg_tcache_nslots--;
- break;
- case 'H':
- if (opt_lg_tcache_nslots + 1 <
- (sizeof(size_t) << 3))
- opt_lg_tcache_nslots++;
- break;
-#endif
- case 'j':
- opt_junk = false;
- break;
- case 'J':
- opt_junk = true;
- break;
- case 'k':
- /*
- * Chunks always require at least one
- * header page, plus enough room to
- * hold a run for the largest medium
- * size class (one page more than the
- * size).
- */
- if ((1U << (opt_lg_chunk - 1)) >=
- (2U << PAGE_SHIFT) + (1U <<
- opt_lg_medium_max))
- opt_lg_chunk--;
- break;
- case 'K':
- if (opt_lg_chunk + 1 <
- (sizeof(size_t) << 3))
- opt_lg_chunk++;
- break;
- case 'm':
-#ifdef MALLOC_DSS
- opt_mmap = false;
-#endif
- break;
- case 'M':
-#ifdef MALLOC_DSS
- opt_mmap = true;
-#endif
- break;
- case 'n':
- opt_narenas_lshift--;
- break;
- case 'N':
- opt_narenas_lshift++;
- break;
- case 'p':
- opt_stats_print = false;
- break;
- case 'P':
- opt_stats_print = true;
- break;
- case 'q':
- if (opt_lg_qspace_max > LG_QUANTUM)
- opt_lg_qspace_max--;
- break;
- case 'Q':
- if (opt_lg_qspace_max + 1 <
- opt_lg_cspace_max)
- opt_lg_qspace_max++;
- break;
- case 'u':
- opt_utrace = false;
- break;
- case 'U':
- opt_utrace = true;
- break;
- case 'v':
- opt_sysv = false;
- break;
- case 'V':
- opt_sysv = true;
- break;
- case 'x':
- opt_xmalloc = false;
- break;
- case 'X':
- opt_xmalloc = true;
- break;
- case 'z':
- opt_zero = false;
- break;
- case 'Z':
- opt_zero = true;
- break;
- default: {
- char cbuf[2];
-
- cbuf[0] = opts[j];
- cbuf[1] = '\0';
- _malloc_message(_getprogname(),
- ": (malloc) Unsupported character "
- "in malloc options: '", cbuf,
- "'\n");
- }
- }
- }
- }
- }
-
-#ifdef MALLOC_DSS
- /* Make sure that there is some method for acquiring memory. */
- if (opt_dss == false && opt_mmap == false)
- opt_mmap = true;
-#endif
- if (opt_stats_print) {
- /* Print statistics at exit. */
- atexit(stats_print_atexit);
- }
-
-
- /* Set variables according to the value of opt_lg_[qc]space_max. */
- qspace_max = (1U << opt_lg_qspace_max);
- cspace_min = CACHELINE_CEILING(qspace_max);
- if (cspace_min == qspace_max)
- cspace_min += CACHELINE;
- cspace_max = (1U << opt_lg_cspace_max);
- sspace_min = SUBPAGE_CEILING(cspace_max);
- if (sspace_min == cspace_max)
- sspace_min += SUBPAGE;
- assert(sspace_min < PAGE_SIZE);
- sspace_max = PAGE_SIZE - SUBPAGE;
- medium_max = (1U << opt_lg_medium_max);
-
-#ifdef MALLOC_TINY
- assert(LG_QUANTUM >= LG_TINY_MIN);
-#endif
- assert(ntbins <= LG_QUANTUM);
- nqbins = qspace_max >> LG_QUANTUM;
- ncbins = ((cspace_max - cspace_min) >> LG_CACHELINE) + 1;
- nsbins = ((sspace_max - sspace_min) >> LG_SUBPAGE) + 1;
-
- /*
- * Compute medium size class spacing and the number of medium size
- * classes. Limit spacing to no more than pagesize, but if possible
- * use the smallest spacing that does not exceed NMBINS_MAX medium size
- * classes.
- */
- lg_mspace = LG_SUBPAGE;
- nmbins = ((medium_max - medium_min) >> lg_mspace) + 1;
- while (lg_mspace < PAGE_SHIFT && nmbins > NMBINS_MAX) {
- lg_mspace = lg_mspace + 1;
- nmbins = ((medium_max - medium_min) >> lg_mspace) + 1;
- }
- mspace_mask = (1U << lg_mspace) - 1U;
-
- mbin0 = ntbins + nqbins + ncbins + nsbins;
- nbins = mbin0 + nmbins;
- /*
- * The small_size2bin lookup table uses uint8_t to encode each bin
- * index, so we cannot support more than 256 small size classes. This
- * limit is difficult to exceed (not even possible with 16B quantum and
- * 4KiB pages), and such configurations are impractical, but
- * nonetheless we need to protect against this case in order to avoid
- * undefined behavior.
- */
- if (mbin0 > 256) {
- char line_buf[UMAX2S_BUFSIZE];
- _malloc_message(_getprogname(),
- ": (malloc) Too many small size classes (",
- umax2s(mbin0, 10, line_buf), " > max 256)\n");
- abort();
- }
-
- if (small_size2bin_init()) {
- malloc_mutex_unlock(&init_lock);
- return (true);
- }
-
-#ifdef MALLOC_TCACHE
- if (opt_lg_tcache_nslots > 0) {
- tcache_nslots = (1U << opt_lg_tcache_nslots);
-
- /* Compute incremental GC event threshold. */
- if (opt_lg_tcache_gc_sweep >= 0) {
- tcache_gc_incr = ((1U << opt_lg_tcache_gc_sweep) /
- nbins) + (((1U << opt_lg_tcache_gc_sweep) % nbins ==
- 0) ? 0 : 1);
- } else
- tcache_gc_incr = 0;
- } else
- tcache_nslots = 0;
-#endif
-
- /* Set variables according to the value of opt_lg_chunk. */
- chunksize = (1LU << opt_lg_chunk);
- chunksize_mask = chunksize - 1;
- chunk_npages = (chunksize >> PAGE_SHIFT);
- {
- size_t header_size;
-
- /*
- * Compute the header size such that it is large enough to
- * contain the page map.
- */
- header_size = sizeof(arena_chunk_t) +
- (sizeof(arena_chunk_map_t) * (chunk_npages - 1));
- arena_chunk_header_npages = (header_size >> PAGE_SHIFT) +
- ((header_size & PAGE_MASK) != 0);
- }
- arena_maxclass = chunksize - (arena_chunk_header_npages <<
- PAGE_SHIFT);
-
- UTRACE((void *)(intptr_t)(-1), 0, 0);
-
-#ifdef MALLOC_STATS
- malloc_mutex_init(&chunks_mtx);
- memset(&stats_chunks, 0, sizeof(chunk_stats_t));
-#endif
-
- /* Various sanity checks that regard configuration. */
- assert(chunksize >= PAGE_SIZE);
-
- /* Initialize chunks data. */
- malloc_mutex_init(&huge_mtx);
- extent_tree_ad_new(&huge);
-#ifdef MALLOC_DSS
- malloc_mutex_init(&dss_mtx);
- dss_base = sbrk(0);
- dss_prev = dss_base;
- dss_max = dss_base;
- extent_tree_szad_new(&dss_chunks_szad);
- extent_tree_ad_new(&dss_chunks_ad);
-#endif
-#ifdef MALLOC_STATS
- huge_nmalloc = 0;
- huge_ndalloc = 0;
- huge_allocated = 0;
-#endif
-
- /* Initialize base allocation data structures. */
-#ifdef MALLOC_STATS
- base_mapped = 0;
-#endif
-#ifdef MALLOC_DSS
- /*
- * Allocate a base chunk here, since it doesn't actually have to be
- * chunk-aligned. Doing this before allocating any other chunks allows
- * the use of space that would otherwise be wasted.
- */
- if (opt_dss)
- base_pages_alloc(0);
-#endif
- base_nodes = NULL;
- malloc_mutex_init(&base_mtx);
-
- if (ncpus > 1) {
- /*
- * For SMP systems, create more than one arena per CPU by
- * default.
- */
-#ifdef MALLOC_TCACHE
- if (tcache_nslots) {
- /*
- * Only large object allocation/deallocation is
- * guaranteed to acquire an arena mutex, so we can get
- * away with fewer arenas than without thread caching.
- */
- opt_narenas_lshift += 1;
- } else {
-#endif
- /*
- * All allocations must acquire an arena mutex, so use
- * plenty of arenas.
- */
- opt_narenas_lshift += 2;
-#ifdef MALLOC_TCACHE
- }
-#endif
- }
-
- /* Determine how many arenas to use. */
- narenas = ncpus;
- if (opt_narenas_lshift > 0) {
- if ((narenas << opt_narenas_lshift) > narenas)
- narenas <<= opt_narenas_lshift;
- /*
- * Make sure not to exceed the limits of what base_alloc() can
- * handle.
- */
- if (narenas * sizeof(arena_t *) > chunksize)
- narenas = chunksize / sizeof(arena_t *);
- } else if (opt_narenas_lshift < 0) {
- if ((narenas >> -opt_narenas_lshift) < narenas)
- narenas >>= -opt_narenas_lshift;
- /* Make sure there is at least one arena. */
- if (narenas == 0)
- narenas = 1;
- }
-
-#ifdef NO_TLS
- if (narenas > 1) {
- static const unsigned primes[] = {1, 3, 5, 7, 11, 13, 17, 19,
- 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83,
- 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149,
- 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211,
- 223, 227, 229, 233, 239, 241, 251, 257, 263};
- unsigned nprimes, parenas;
-
- /*
- * Pick a prime number of hash arenas that is more than narenas
- * so that direct hashing of pthread_self() pointers tends to
- * spread allocations evenly among the arenas.
- */
- assert((narenas & 1) == 0); /* narenas must be even. */
- nprimes = (sizeof(primes) >> LG_SIZEOF_INT);
- parenas = primes[nprimes - 1]; /* In case not enough primes. */
- for (i = 1; i < nprimes; i++) {
- if (primes[i] > narenas) {
- parenas = primes[i];
- break;
- }
- }
- narenas = parenas;
- }
-#endif
-
-#ifndef NO_TLS
- next_arena = 0;
-#endif
-
- /* Allocate and initialize arenas. */
- arenas = (arena_t **)base_alloc(sizeof(arena_t *) * narenas);
- if (arenas == NULL) {
- malloc_mutex_unlock(&init_lock);
- return (true);
- }
- /*
- * Zero the array. In practice, this should always be pre-zeroed,
- * since it was just mmap()ed, but let's be sure.
- */
- memset(arenas, 0, sizeof(arena_t *) * narenas);
-
- /*
- * Initialize one arena here. The rest are lazily created in
- * choose_arena_hard().
- */
- arenas_extend(0);
- if (arenas[0] == NULL) {
- malloc_mutex_unlock(&init_lock);
- return (true);
- }
-#ifndef NO_TLS
- /*
- * Assign the initial arena to the initial thread, in order to avoid
- * spurious creation of an extra arena if the application switches to
- * threaded mode.
- */
- arenas_map = arenas[0];
-#endif
- malloc_spin_init(&arenas_lock);
-
- malloc_initialized = true;
- malloc_mutex_unlock(&init_lock);
- return (false);
-}
-
-/*
- * End general internal functions.
- */
-/******************************************************************************/
-/*
- * Begin malloc(3)-compatible functions.
- */
-
-void *
-malloc(size_t size)
-{
- void *ret;
-
- if (malloc_init()) {
- ret = NULL;
- goto OOM;
- }
-
- if (size == 0) {
- if (opt_sysv == false)
- size = 1;
- else {
- if (opt_xmalloc) {
- _malloc_message(_getprogname(),
- ": (malloc) Error in malloc(): "
- "invalid size 0\n", "", "");
- abort();
- }
- ret = NULL;
- goto RETURN;
- }
- }
-
- ret = imalloc(size);
-
-OOM:
- if (ret == NULL) {
- if (opt_xmalloc) {
- _malloc_message(_getprogname(),
- ": (malloc) Error in malloc(): out of memory\n", "",
- "");
- abort();
- }
- errno = ENOMEM;
- }
-
-RETURN:
- UTRACE(0, size, ret);
- return (ret);
-}
-
-int
-posix_memalign(void **memptr, size_t alignment, size_t size)
-{
- int ret;
- void *result;
-
- if (malloc_init())
- result = NULL;
- else {
- if (size == 0) {
- if (opt_sysv == false)
- size = 1;
- else {
- if (opt_xmalloc) {
- _malloc_message(_getprogname(),
- ": (malloc) Error in "
- "posix_memalign(): invalid "
- "size 0\n", "", "");
- abort();
- }
- result = NULL;
- *memptr = NULL;
- ret = 0;
- goto RETURN;
- }
- }
-
- /* Make sure that alignment is a large enough power of 2. */
- if (((alignment - 1) & alignment) != 0
- || alignment < sizeof(void *)) {
- if (opt_xmalloc) {
- _malloc_message(_getprogname(),
- ": (malloc) Error in posix_memalign(): "
- "invalid alignment\n", "", "");
- abort();
- }
- result = NULL;
- ret = EINVAL;
- goto RETURN;
- }
-
- result = ipalloc(alignment, size);
- }
-
- if (result == NULL) {
- if (opt_xmalloc) {
- _malloc_message(_getprogname(),
- ": (malloc) Error in posix_memalign(): out of memory\n",
- "", "");
- abort();
- }
- ret = ENOMEM;
- goto RETURN;
- }
-
- *memptr = result;
- ret = 0;
-
-RETURN:
- UTRACE(0, size, result);
- return (ret);
-}
-
-void *
-calloc(size_t num, size_t size)
-{
- void *ret;
- size_t num_size;
-
- if (malloc_init()) {
- num_size = 0;
- ret = NULL;
- goto RETURN;
- }
-
- num_size = num * size;
- if (num_size == 0) {
- if ((opt_sysv == false) && ((num == 0) || (size == 0)))
- num_size = 1;
- else {
- ret = NULL;
- goto RETURN;
- }
- /*
- * Try to avoid division here. We know that it isn't possible to
- * overflow during multiplication if neither operand uses any of the
- * most significant half of the bits in a size_t.
- */
- } else if (((num | size) & (SIZE_T_MAX << (sizeof(size_t) << 2)))
- && (num_size / size != num)) {
- /* size_t overflow. */
- ret = NULL;
- goto RETURN;
- }
-
- ret = icalloc(num_size);
-
-RETURN:
- if (ret == NULL) {
- if (opt_xmalloc) {
- _malloc_message(_getprogname(),
- ": (malloc) Error in calloc(): out of memory\n", "",
- "");
- abort();
- }
- errno = ENOMEM;
- }
-
- UTRACE(0, num_size, ret);
- return (ret);
-}
-
-void *
-realloc(void *ptr, size_t size)
-{
- void *ret;
-
- if (size == 0) {
- if (opt_sysv == false)
- size = 1;
- else {
- if (ptr != NULL)
- idalloc(ptr);
- ret = NULL;
- goto RETURN;
- }
- }
-
- if (ptr != NULL) {
- assert(malloc_initialized);
-
- ret = iralloc(ptr, size);
-
- if (ret == NULL) {
- if (opt_xmalloc) {
- _malloc_message(_getprogname(),
- ": (malloc) Error in realloc(): out of "
- "memory\n", "", "");
- abort();
- }
- errno = ENOMEM;
- }
- } else {
- if (malloc_init())
- ret = NULL;
- else
- ret = imalloc(size);
-
- if (ret == NULL) {
- if (opt_xmalloc) {
- _malloc_message(_getprogname(),
- ": (malloc) Error in realloc(): out of "
- "memory\n", "", "");
- abort();
- }
- errno = ENOMEM;
- }
- }
-
-RETURN:
- UTRACE(ptr, size, ret);
- return (ret);
-}
-
-void
-free(void *ptr)
-{
-
- UTRACE(ptr, 0, 0);
- if (ptr != NULL) {
- assert(malloc_initialized);
-
- idalloc(ptr);
- }
-}
-
-/*
- * End malloc(3)-compatible functions.
- */
-/******************************************************************************/
-/*
- * Begin non-standard functions.
- */
-
-size_t
-malloc_usable_size(const void *ptr)
-{
-
- assert(ptr != NULL);
-
- return (isalloc(ptr));
-}
-
-/*
- * End non-standard functions.
- */
-/******************************************************************************/
-/*
- * Begin library-private functions.
- */
-
-/*
- * We provide an unpublished interface in order to receive notifications from
- * the pthreads library whenever a thread exits. This allows us to clean up
- * thread caches.
- */
-void
-_malloc_thread_cleanup(void)
-{
-
-#ifdef MALLOC_TCACHE
- tcache_t *tcache = tcache_tls;
-
- if (tcache != NULL) {
- assert(tcache != (void *)(uintptr_t)1);
- tcache_destroy(tcache);
- tcache_tls = (void *)(uintptr_t)1;
- }
-#endif
-}
-
-/*
- * The following functions are used by threading libraries for protection of
- * malloc during fork(). These functions are only called if the program is
- * running in threaded mode, so there is no need to check whether the program
- * is threaded here.
- */
-
-void
-_malloc_prefork(void)
-{
- unsigned i;
-
- /* Acquire all mutexes in a safe order. */
- malloc_spin_lock(&arenas_lock);
- for (i = 0; i < narenas; i++) {
- if (arenas[i] != NULL)
- malloc_spin_lock(&arenas[i]->lock);
- }
-
- malloc_mutex_lock(&base_mtx);
-
- malloc_mutex_lock(&huge_mtx);
-
-#ifdef MALLOC_DSS
- malloc_mutex_lock(&dss_mtx);
-#endif
-}
-
-void
-_malloc_postfork(void)
-{
- unsigned i;
-
- /* Release all mutexes, now that fork() has completed. */
-
-#ifdef MALLOC_DSS
- malloc_mutex_unlock(&dss_mtx);
-#endif
-
- malloc_mutex_unlock(&huge_mtx);
-
- malloc_mutex_unlock(&base_mtx);
-
- for (i = 0; i < narenas; i++) {
- if (arenas[i] != NULL)
- malloc_spin_unlock(&arenas[i]->lock);
- }
- malloc_spin_unlock(&arenas_lock);
-}
-
-/*
- * End library-private functions.
- */
-/******************************************************************************/
diff --git a/lib/libc/stdlib/ptsname.3 b/lib/libc/stdlib/ptsname.3
index 48da3bd..8e8ec07 100644
--- a/lib/libc/stdlib/ptsname.3
+++ b/lib/libc/stdlib/ptsname.3
@@ -102,7 +102,8 @@ of the slave device on success; otherwise a
pointer is returned.
.Sh ERRORS
The
-.Fn grantpt
+.Fn grantpt ,
+.Fn ptsname
and
.Fn unlockpt
functions may fail and set
diff --git a/lib/libc/stdlib/ptsname.c b/lib/libc/stdlib/ptsname.c
index 40b140d..3e4d4c0 100644
--- a/lib/libc/stdlib/ptsname.c
+++ b/lib/libc/stdlib/ptsname.c
@@ -77,7 +77,6 @@ ptsname(int fildes)
{
static char pt_slave[sizeof _PATH_DEV + SPECNAMELEN] = _PATH_DEV;
char *ret = NULL;
- int sverrno = errno;
/* Make sure fildes points to a master device. */
if (__isptmaster(fildes) != 0)
@@ -87,7 +86,6 @@ ptsname(int fildes)
sizeof pt_slave - (sizeof _PATH_DEV - 1)) != NULL)
ret = pt_slave;
-done: /* Make sure ptsname() does not overwrite errno. */
- errno = sverrno;
+done:
return (ret);
}
diff --git a/lib/libc/stdlib/quick_exit.3 b/lib/libc/stdlib/quick_exit.3
index 06fde8b..f2ea379 100644
--- a/lib/libc/stdlib/quick_exit.3
+++ b/lib/libc/stdlib/quick_exit.3
@@ -54,4 +54,5 @@ function does not return.
.Sh STANDARDS
The
.Fn quick_exit
-function conforms to the C1x draft specification.
+function conforms to
+.St -isoC-2011 .
diff --git a/lib/libc/stdlib/rand.3 b/lib/libc/stdlib/rand.3
index 3eb1a1d..390a40b 100644
--- a/lib/libc/stdlib/rand.3
+++ b/lib/libc/stdlib/rand.3
@@ -32,7 +32,7 @@
.\" @(#)rand.3 8.1 (Berkeley) 6/4/93
.\" $FreeBSD$
.\"
-.Dd October 6, 2010
+.Dd September 4, 2012
.Dt RAND 3
.Os
.Sh NAME
@@ -55,9 +55,15 @@
.Fn rand_r "unsigned *ctx"
.Sh DESCRIPTION
.Bf -symbolic
+The functions described in this manual page are not cryptographically
+secure.
+Cryptographic applications should use
+.Xr arc4random 3
+instead.
+.Ef
+.Pp
These interfaces are obsoleted by
.Xr random 3 .
-.Ef
.Pp
The
.Fn rand
@@ -88,9 +94,6 @@ The
function initializes a seed using the
.Xr random 4
random number device which returns good random numbers.
-However, the
-.Fn rand
-function still remains unsuitable for cryptographic use.
.Pp
The
.Fn rand_r
@@ -105,8 +108,6 @@ For better generator quality, use
.Xr random 3
or
.Xr lrand48 3 .
-Applications requiring cryptographic quality randomness should use
-.Xr arc4random 3 .
.Sh SEE ALSO
.Xr arc4random 3 ,
.Xr lrand48 3 ,
diff --git a/lib/libc/stdlib/rand.c b/lib/libc/stdlib/rand.c
index 077c1ba..7041818 100644
--- a/lib/libc/stdlib/rand.c
+++ b/lib/libc/stdlib/rand.c
@@ -121,7 +121,7 @@ sranddev()
int fd, done;
done = 0;
- fd = _open("/dev/random", O_RDONLY, 0);
+ fd = _open("/dev/random", O_RDONLY | O_CLOEXEC, 0);
if (fd >= 0) {
if (_read(fd, (void *) &next, sizeof(next)) == sizeof(next))
done = 1;
@@ -130,10 +130,9 @@ sranddev()
if (!done) {
struct timeval tv;
- unsigned long junk;
gettimeofday(&tv, NULL);
- srand((getpid() << 16) ^ tv.tv_sec ^ tv.tv_usec ^ junk);
+ srand((getpid() << 16) ^ tv.tv_sec ^ tv.tv_usec);
}
}
diff --git a/lib/libc/stdlib/random.3 b/lib/libc/stdlib/random.3
index c6502bf..4817440 100644
--- a/lib/libc/stdlib/random.3
+++ b/lib/libc/stdlib/random.3
@@ -28,7 +28,7 @@
.\" @(#)random.3 8.1 (Berkeley) 6/4/93
.\" $FreeBSD$
.\"
-.Dd June 4, 1993
+.Dd September 4, 2012
.Dt RANDOM 3
.Os
.Sh NAME
@@ -53,6 +53,14 @@
.Ft char *
.Fn setstate "char *state"
.Sh DESCRIPTION
+.Bf -symbolic
+The functions described in this manual page are not cryptographically
+secure.
+Cryptographic applications should use
+.Xr arc4random 3
+instead.
+.Ef
+.Pp
The
.Fn random
function
@@ -98,10 +106,8 @@ as the seed.
.Pp
The
.Fn srandomdev
-routine initializes a state array using the
-.Xr random 4
-random number device which returns good random numbers,
-suitable for cryptographic use.
+routine initializes a state array using data from
+.Xr random 4 .
Note that this particular seeding
procedure can generate states which are impossible to reproduce by
calling
@@ -175,7 +181,6 @@ messages are printed on the standard error output.
.Xr arc4random 3 ,
.Xr lrand48 3 ,
.Xr rand 3 ,
-.Xr srand 3 ,
.Xr random 4
.Sh HISTORY
These
@@ -191,6 +196,3 @@ The historical implementation used to have a very weak seeding; the
random sequence did not vary much with the seed.
The current implementation employs a better pseudo-random number
generator for the initial state calculation.
-.Pp
-Applications requiring cryptographic quality randomness should use
-.Xr arc4random 3 .
diff --git a/lib/libc/stdlib/random.c b/lib/libc/stdlib/random.c
index f7be4a7..a3c054e 100644
--- a/lib/libc/stdlib/random.c
+++ b/lib/libc/stdlib/random.c
@@ -216,10 +216,8 @@ static int rand_deg = DEG_3;
static int rand_sep = SEP_3;
static uint32_t *end_ptr = &randtbl[DEG_3 + 1];
-static inline uint32_t good_rand(int32_t);
-
-static inline uint32_t good_rand (x)
- int32_t x;
+static inline uint32_t
+good_rand(int32_t x)
{
#ifdef USE_WEAK_SEEDING
/*
@@ -264,8 +262,7 @@ static inline uint32_t good_rand (x)
* for default usage relies on values produced by this routine.
*/
void
-srandom(x)
- unsigned long x;
+srandom(unsigned long x)
{
int i, lim;
@@ -295,7 +292,7 @@ srandom(x)
* a fixed seed.
*/
void
-srandomdev()
+srandomdev(void)
{
int fd, done;
size_t len;
@@ -306,7 +303,7 @@ srandomdev()
len = rand_deg * sizeof state[0];
done = 0;
- fd = _open("/dev/random", O_RDONLY, 0);
+ fd = _open("/dev/random", O_RDONLY | O_CLOEXEC, 0);
if (fd >= 0) {
if (_read(fd, (void *) state, len) == (ssize_t) len)
done = 1;
@@ -315,10 +312,9 @@ srandomdev()
if (!done) {
struct timeval tv;
- unsigned long junk;
gettimeofday(&tv, NULL);
- srandom((getpid() << 16) ^ tv.tv_sec ^ tv.tv_usec ^ junk);
+ srandom((getpid() << 16) ^ tv.tv_sec ^ tv.tv_usec);
return;
}
@@ -352,10 +348,7 @@ srandomdev()
* complain about mis-alignment, but you should disregard these messages.
*/
char *
-initstate(seed, arg_state, n)
- unsigned long seed; /* seed for R.N.G. */
- char *arg_state; /* pointer to state array */
- long n; /* # bytes of state info */
+initstate(unsigned long seed, char *arg_state, long n)
{
char *ostate = (char *)(&state[-1]);
uint32_t *int_arg_state = (uint32_t *)arg_state;
@@ -367,7 +360,7 @@ initstate(seed, arg_state, n)
if (n < BREAK_0) {
(void)fprintf(stderr,
"random: not enough state (%ld bytes); ignored.\n", n);
- return(0);
+ return (0);
}
if (n < BREAK_1) {
rand_type = TYPE_0;
@@ -397,7 +390,7 @@ initstate(seed, arg_state, n)
int_arg_state[0] = rand_type;
else
int_arg_state[0] = MAX_TYPES * (rptr - state) + rand_type;
- return(ostate);
+ return (ostate);
}
/*
@@ -420,8 +413,7 @@ initstate(seed, arg_state, n)
* complain about mis-alignment, but you should disregard these messages.
*/
char *
-setstate(arg_state)
- char *arg_state; /* pointer to state array */
+setstate(char *arg_state)
{
uint32_t *new_state = (uint32_t *)arg_state;
uint32_t type = new_state[0] % MAX_TYPES;
@@ -452,7 +444,7 @@ setstate(arg_state)
fptr = &state[(rear + rand_sep) % rand_deg];
}
end_ptr = &state[rand_deg]; /* set end_ptr too */
- return(ostate);
+ return (ostate);
}
/*
@@ -473,7 +465,7 @@ setstate(arg_state)
* Returns a 31-bit random number.
*/
long
-random()
+random(void)
{
uint32_t i;
uint32_t *f, *r;
@@ -498,5 +490,5 @@ random()
fptr = f; rptr = r;
}
- return((long)i);
+ return ((long)i);
}
diff --git a/lib/libc/stdlib/realpath.c b/lib/libc/stdlib/realpath.c
index aded9b2..8fd5457 100644
--- a/lib/libc/stdlib/realpath.c
+++ b/lib/libc/stdlib/realpath.c
@@ -181,8 +181,6 @@ realpath(const char * __restrict path, char * __restrict resolved)
return (NULL);
}
if (lstat(resolved, &sb) != 0) {
- if (errno != ENOENT || p != NULL)
- errno = ENOTDIR;
if (m)
free(resolved);
return (NULL);
diff --git a/lib/libc/string/ffs.3 b/lib/libc/string/ffs.3
index bf6f5f5..d8e11d8 100644
--- a/lib/libc/string/ffs.3
+++ b/lib/libc/string/ffs.3
@@ -30,7 +30,7 @@
.\" @(#)ffs.3 8.2 (Berkeley) 4/19/94
.\" $FreeBSD$
.\"
-.Dd May 3, 2011
+.Dd September 29, 2012
.Dt FFS 3
.Os
.Sh NAME
@@ -63,8 +63,7 @@ The
.Fn ffsl
and
.Fn ffsll
-functions find the first bit set
-(beginning with the least significant bit)
+functions find the first (least significant) bit set
in
.Fa value
and return the index of that bit.
@@ -74,11 +73,11 @@ The
.Fn flsl
and
.Fn flsll
-functions find the last bit set in
+functions find the last (most significant) bit set in
.Fa value
and return the index of that bit.
.Pp
-Bits are numbered starting at 1 (the least significant bit).
+Bits are numbered starting at 1, the least significant bit.
A return value of zero from any of these functions means that the
argument was zero.
.Sh SEE ALSO
diff --git a/lib/libc/string/strerror.3 b/lib/libc/string/strerror.3
index 5961a84..cc25602 100644
--- a/lib/libc/string/strerror.3
+++ b/lib/libc/string/strerror.3
@@ -174,10 +174,10 @@ function was implemented in
by
.An Wes Peters Aq wes@FreeBSD.org .
.Sh BUGS
-For unknown error numbers, the
+The
.Fn strerror
-function will return its result in a static buffer which
-may be overwritten by subsequent calls.
+function returns its result in a static buffer which
+will be overwritten by subsequent calls.
.Pp
The return type for
.Fn strerror
diff --git a/lib/libc/string/strsignal.c b/lib/libc/string/strsignal.c
index c51f34d..8fc1f85 100644
--- a/lib/libc/string/strsignal.c
+++ b/lib/libc/string/strsignal.c
@@ -120,29 +120,29 @@ strsignal(int num)
UPREFIX,
#endif
sizeof(sig_ebuf));
- }
- signum = num;
- if (num < 0)
- signum = -signum;
-
- t = tmp;
- do {
- *t++ = "0123456789"[signum % 10];
- } while (signum /= 10);
- if (num < 0)
- *t++ = '-';
-
- p = (ebuf + n);
- *p++ = ':';
- *p++ = ' ';
-
- for (;;) {
- *p++ = *--t;
- if (t <= tmp)
- break;
+ signum = num;
+ if (num < 0)
+ signum = -signum;
+
+ t = tmp;
+ do {
+ *t++ = "0123456789"[signum % 10];
+ } while (signum /= 10);
+ if (num < 0)
+ *t++ = '-';
+
+ p = (ebuf + n);
+ *p++ = ':';
+ *p++ = ' ';
+
+ for (;;) {
+ *p++ = *--t;
+ if (t <= tmp)
+ break;
+ }
+ *p = '\0';
}
- *p = '\0';
#if defined(NLS)
catclose(catd);
diff --git a/lib/libc/sys/Symbol.map b/lib/libc/sys/Symbol.map
index 6888ea0..008b8da 100644
--- a/lib/libc/sys/Symbol.map
+++ b/lib/libc/sys/Symbol.map
@@ -379,6 +379,7 @@ FBSD_1.2 {
};
FBSD_1.3 {
+ clock_getcpuclockid2;
ffclock_getcounter;
ffclock_getestimate;
ffclock_setestimate;
@@ -490,6 +491,8 @@ FBSDprivate_1.0 {
__sys_chown;
_chroot;
__sys_chroot;
+ _clock_getcpuclockid2;
+ __sys_clock_getcpuclockid2;
_clock_getres;
__sys_clock_getres;
_clock_gettime;
diff --git a/lib/libc/sys/dup.2 b/lib/libc/sys/dup.2
index d2a4b7e..7a07c21 100644
--- a/lib/libc/sys/dup.2
+++ b/lib/libc/sys/dup.2
@@ -138,6 +138,7 @@ is not a valid active descriptor
.It Bq Er EMFILE
Too many descriptors are active.
.El
+.Pp
The
.Fn dup2
system call fails if:
diff --git a/lib/libc/sys/fcntl.2 b/lib/libc/sys/fcntl.2
index beceb72..c174563 100644
--- a/lib/libc/sys/fcntl.2
+++ b/lib/libc/sys/fcntl.2
@@ -28,7 +28,7 @@
.\" @(#)fcntl.2 8.2 (Berkeley) 1/12/94
.\" $FreeBSD$
.\"
-.Dd January 28, 2012
+.Dd July 27, 2012
.Dt FCNTL 2
.Os
.Sh NAME
@@ -54,7 +54,7 @@ Depending on the value of
.Fn fcntl
can take an additional third argument
.Fa "int arg" .
-.Bl -tag -width F_GETOWNX
+.Bl -tag -width F_DUP2FD_CLOEXEC
.It Dv F_DUPFD
Return a new descriptor as follows:
.Pp
@@ -73,23 +73,44 @@ Same access mode (read, write or read/write).
Same file status flags (i.e., both file descriptors
share the same file status flags).
.It
-The close-on-exec flag associated with the new file descriptor
-is set to remain open across
+The close-on-exec flag
+.Dv FD_CLOEXEC
+associated with the new file descriptor is cleared, so the file descriptor is
+to remain open across
.Xr execve 2
system calls.
.El
+.It Dv F_DUPFD_CLOEXEC
+Like
+.Dv F_DUPFD ,
+but the
+.Dv FD_CLOEXEC
+flag associated with the new file descriptor is set, so the file descriptor
+is closed when
+.Xr execve 2
+system call executes.
.It Dv F_DUP2FD
It is functionally equivalent to
.Bd -literal -offset indent
dup2(fd, arg)
.Ed
+.It Dv F_DUP2FD_CLOEXEC
+Like
+.Dv F_DUP2FD ,
+but the
+.Dv FD_CLOEXEC
+flag associated with the new file descriptor is set.
.Pp
The
.Dv F_DUP2FD
-constant is not portable, so it should not be used if portability is needed.
+and
+.Dv F_DUP2FD_CLOEXEC
+constants are not portable, so they should not be used if
+portability is needed.
Use
.Fn dup2
-instead.
+instead of
+.Dv F_DUP2FD .
.It Dv F_GETFD
Get the close-on-exec flag associated with the file descriptor
.Fa fd
diff --git a/lib/libc/sys/fcntl.c b/lib/libc/sys/fcntl.c
index 470f8ab..480cc40 100644
--- a/lib/libc/sys/fcntl.c
+++ b/lib/libc/sys/fcntl.c
@@ -41,7 +41,7 @@ __fcntl_compat(int fd, int cmd, ...)
{
va_list args;
long arg;
- struct oflock ofl;
+ struct __oflock ofl;
struct flock *flp;
int res;
diff --git a/lib/libc/sys/kill.2 b/lib/libc/sys/kill.2
index 0389559..98c3050 100644
--- a/lib/libc/sys/kill.2
+++ b/lib/libc/sys/kill.2
@@ -64,11 +64,19 @@ This can be used to check the validity of
For a process to have permission to send a signal to a process designated
by
.Fa pid ,
-the real or effective user ID of the receiving process must match
-that of the sending process or the user must have appropriate privileges
-(such as given by a set-user-ID program or the user is the super-user).
+the user must be the super-user, or
+the real or saved user ID of the receiving process must match
+the real or effective user ID of the sending process.
A single exception is the signal SIGCONT, which may always be sent
-to any process with the same session ID as the caller.
+to any process with the same session ID as the sender.
+In addition, if the
+.Va security.bsd.conservative_signals
+.Xr sysctl
+is set to 1, the user is not a super-user, and
+the receiver is set-uid, then
+only job control and terminal control signals may
+be sent (in particular, only SIGKILL, SIGINT, SIGTERM, SIGALRM,
+SIGSTOP, SIGTTIN, SIGTTOU, SIGTSTP, SIGHUP, SIGUSR1, SIGUSR2).
.Bl -tag -width Ds
.It \&If Fa pid No \&is greater than zero :
The
@@ -124,10 +132,9 @@ is not a valid signal number.
No process or process group can be found corresponding to that specified by
.Fa pid .
.It Bq Er EPERM
-The sending process is not the super-user and its effective
-user id does not match the effective user-id of the receiving process.
-When signaling a process group, this error is returned if any members
-of the group could not be signaled.
+The sending process does not have permission to send
+.Va sig
+to the receiving process.
.El
.Sh SEE ALSO
.Xr getpgrp 2 ,
diff --git a/lib/libc/sys/listen.2 b/lib/libc/sys/listen.2
index bd6abde..ab22fd1 100644
--- a/lib/libc/sys/listen.2
+++ b/lib/libc/sys/listen.2
@@ -28,7 +28,7 @@
.\" From: @(#)listen.2 8.2 (Berkeley) 12/11/93
.\" $FreeBSD$
.\"
-.Dd August 29, 2005
+.Dd October 20, 2012
.Dt LISTEN 2
.Os
.Sh NAME
@@ -102,15 +102,15 @@ of service attacks are no longer necessary.
The
.Xr sysctl 3
MIB variable
-.Va kern.ipc.somaxconn
+.Va kern.ipc.soacceptqueue
specifies a hard limit on
.Fa backlog ;
if a value greater than
-.Va kern.ipc.somaxconn
+.Va kern.ipc.soacceptqueue
or less than zero is specified,
.Fa backlog
is silently forced to
-.Va kern.ipc.somaxconn .
+.Va kern.ipc.soacceptqueue .
.Sh INTERACTION WITH ACCEPT FILTERS
When accept filtering is used on a socket, a second queue will
be used to hold sockets that have connected, but have not yet
@@ -168,3 +168,17 @@ at run-time, and to use a negative
.Fa backlog
to request the maximum allowable value, was introduced in
.Fx 2.2 .
+The
+.Va kern.ipc.somaxconn
+.Xr sysctl 3
+has been replaced with
+.Va kern.ipc.soacceptqueue
+in
+.Fx 10.0
+to prevent confusion about its actual functionality.
+The original
+.Xr sysctl 3
+.Va kern.ipc.somaxconn
+is still available but hidden from a
+.Xr sysctl 3
+-a output so that existing applications and scripts continue to work.
diff --git a/lib/libc/sys/recv.2 b/lib/libc/sys/recv.2
index 66f311f..74f275c 100644
--- a/lib/libc/sys/recv.2
+++ b/lib/libc/sys/recv.2
@@ -28,7 +28,7 @@
.\" @(#)recv.2 8.3 (Berkeley) 2/21/94
.\" $FreeBSD$
.\"
-.Dd December 28, 2006
+.Dd September 12, 2012
.Dt RECV 2
.Os
.Sh NAME
@@ -44,7 +44,7 @@
.Ft ssize_t
.Fn recv "int s" "void *buf" "size_t len" "int flags"
.Ft ssize_t
-.Fn recvfrom "int s" "void * restrict buf" "size_t len" "int flags" "struct sockaddr * restrict from" "socklen_t * restrict fromlen"
+.Fn recvfrom "int s" "void *buf" "size_t len" "int flags" "struct sockaddr * restrict from" "socklen_t * restrict fromlen"
.Ft ssize_t
.Fn recvmsg "int s" "struct msghdr *msg" "int flags"
.Sh DESCRIPTION
@@ -252,8 +252,21 @@ struct cmsgcred {
};
.Ed
.Pp
-The kernel will fill in the credential information of the sending process
-and deliver it to the receiver.
+If a sender supplies ancillary data with enough space for the above struct
+tagged as
+.Dv SCM_CREDS
+control message type to the
+.Fn sendmsg
+system call, then kernel will fill in the credential information of the
+sending process and deliver it to the receiver.
+Since receiver usually has no control over a sender, this method of retrieving
+credential information isn't reliable.
+For reliable retrieval of remote side credentials it is advised to use the
+.Dv LOCAL_CREDS
+socket option on the receiving socket.
+See
+.Xr unix 4
+for details.
.Pp
The
.Fa msg_flags
@@ -322,7 +335,8 @@ address space.
.Xr getsockopt 2 ,
.Xr read 2 ,
.Xr select 2 ,
-.Xr socket 2
+.Xr socket 2 ,
+.Xr unix 4
.Sh HISTORY
The
.Fn recv
diff --git a/lib/libc/sys/sigaction.2 b/lib/libc/sys/sigaction.2
index 47b3a72..e161bf2 100644
--- a/lib/libc/sys/sigaction.2
+++ b/lib/libc/sys/sigaction.2
@@ -28,7 +28,7 @@
.\" From: @(#)sigaction.2 8.2 (Berkeley) 4/3/94
.\" $FreeBSD$
.\"
-.Dd April 18, 2010
+.Dd September 27, 2012
.Dt SIGACTION 2
.Os
.Sh NAME
@@ -586,13 +586,6 @@ system call
will fail and no new signal handler will be installed if one
of the following occurs:
.Bl -tag -width Er
-.It Bq Er EFAULT
-Either
-.Fa act
-or
-.Fa oact
-points to memory that is not a valid part of the process
-address space.
.It Bq Er EINVAL
The
.Fa sig
diff --git a/lib/libc/sys/sigwait.2 b/lib/libc/sys/sigwait.2
index a9e605c..525bffb 100644
--- a/lib/libc/sys/sigwait.2
+++ b/lib/libc/sys/sigwait.2
@@ -27,7 +27,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd August 24, 2011
+.Dd September 27, 2012
.Dt SIGWAIT 2
.Os
.Sh NAME
@@ -107,9 +107,6 @@ The
.Fa set
argument
specifies one or more invalid signal numbers.
-.It Bq Er EFAULT
-Any arguments point outside the allocated address space or there is a
-memory protection fault.
.El
.Sh SEE ALSO
.Xr sigaction 2 ,
diff --git a/lib/libc/sys/sigwaitinfo.2 b/lib/libc/sys/sigwaitinfo.2
index a83de06..9109759 100644
--- a/lib/libc/sys/sigwaitinfo.2
+++ b/lib/libc/sys/sigwaitinfo.2
@@ -27,7 +27,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd August 24, 2011
+.Dd September 27, 2012
.Dt SIGTIMEDWAIT 2
.Os
.Sh NAME
@@ -172,9 +172,6 @@ system calls fail if:
.Bl -tag -width Er
.It Bq Er EINTR
The wait was interrupted by an unblocked, caught signal.
-.It Bq Er EFAULT
-Any arguments point outside the allocated address space or there is a
-memory protection fault.
.Pp
.El
The
diff --git a/lib/libc/sys/wait.2 b/lib/libc/sys/wait.2
index e4812fc..71bd529 100644
--- a/lib/libc/sys/wait.2
+++ b/lib/libc/sys/wait.2
@@ -177,7 +177,7 @@ with a
value of -1.
.Pp
The following macros may be used to test the manner of exit of the process.
-One of the first three macros will evaluate to a non-zero (true) value:
+One of the first four macros will evaluate to a non-zero (true) value:
.Bl -tag -width Ds
.It Fn WIFCONTINUED status
True if the process has not terminated, and
diff --git a/lib/libc/yp/yplib.c b/lib/libc/yp/yplib.c
index 3dfc0aa..1778c6a 100644
--- a/lib/libc/yp/yplib.c
+++ b/lib/libc/yp/yplib.c
@@ -375,7 +375,7 @@ again:
ysd->dom_socket = -1;
}
snprintf(path, sizeof(path), "%s/%s.%d", BINDINGDIR, dom, 2);
- if ((fd = _open(path, O_RDONLY)) == -1) {
+ if ((fd = _open(path, O_RDONLY | O_CLOEXEC)) == -1) {
/* no binding file, YP is dead. */
/* Try to bring it back to life. */
_close(fd);
diff --git a/lib/libdwarf/dwarf.h b/lib/libdwarf/dwarf.h
index ecbafcf..6eb2077 100644
--- a/lib/libdwarf/dwarf.h
+++ b/lib/libdwarf/dwarf.h
@@ -184,6 +184,7 @@
#define DW_FORM_ref8 0x14
#define DW_FORM_ref_udata 0x15
#define DW_FORM_indirect 0x16
+#define DW_FORM_flag_present 0x19
#define DW_OP_addr 0x03
#define DW_OP_deref 0x06
diff --git a/lib/libdwarf/dwarf_attrval.c b/lib/libdwarf/dwarf_attrval.c
index db07ee7..25286de 100644
--- a/lib/libdwarf/dwarf_attrval.c
+++ b/lib/libdwarf/dwarf_attrval.c
@@ -101,6 +101,7 @@ dwarf_attrval_flag(Dwarf_Die die, uint64_t attr, Dwarf_Bool *valp, Dwarf_Error *
} else {
switch (av->av_form) {
case DW_FORM_flag:
+ case DW_FORM_flag_present:
*valp = (Dwarf_Bool) av->u[0].u64;
break;
default:
diff --git a/lib/libdwarf/dwarf_dump.c b/lib/libdwarf/dwarf_dump.c
index e92fee0d..dc22800 100644
--- a/lib/libdwarf/dwarf_dump.c
+++ b/lib/libdwarf/dwarf_dump.c
@@ -240,6 +240,8 @@ get_form_desc(uint32_t form)
return "DW_FORM_data8";
case DW_FORM_flag:
return "DW_FORM_flag";
+ case DW_FORM_flag_present:
+ return "DW_FORM_flag_present";
case DW_FORM_indirect:
return "DW_FORM_indirect";
case DW_FORM_ref1:
@@ -648,6 +650,7 @@ dwarf_dump_av(Dwarf_Die die, Dwarf_AttrValue av)
case DW_FORM_data4:
case DW_FORM_data8:
case DW_FORM_flag:
+ case DW_FORM_flag_present:
printf("%llu", (unsigned long long) av->u[0].u64);
break;
case DW_FORM_ref1:
diff --git a/lib/libdwarf/dwarf_errmsg.c b/lib/libdwarf/dwarf_errmsg.c
index ffc2020..ca37740 100644
--- a/lib/libdwarf/dwarf_errmsg.c
+++ b/lib/libdwarf/dwarf_errmsg.c
@@ -29,7 +29,7 @@
#include <stdio.h>
#include "_libdwarf.h"
-const char *_libdwarf_errors[] = {
+static const char *_libdwarf_errors[] = {
#define DEFINE_ERROR(N,S) [DWARF_E_##N] = S
DEFINE_ERROR(NONE, "No Error"),
DEFINE_ERROR(ERROR, "An error"),
diff --git a/lib/libdwarf/dwarf_init.c b/lib/libdwarf/dwarf_init.c
index 95642a0..6ebc7d9 100644
--- a/lib/libdwarf/dwarf_init.c
+++ b/lib/libdwarf/dwarf_init.c
@@ -396,6 +396,10 @@ dwarf_init_attr(Dwarf_Debug dbg, Elf_Data **dp, uint64_t *offsetp,
avref.u[1].s = elf_strptr(dbg->dbg_elf,
dbg->dbg_s[DWARF_debug_str].s_shnum, avref.u[0].u64);
break;
+ case DW_FORM_flag_present:
+ /* This form has no value encoded in the DIE. */
+ avref.u[0].u64 = 1;
+ break;
default:
DWARF_SET_ERROR(error, DWARF_E_NOT_IMPLEMENTED);
ret = DWARF_E_NOT_IMPLEMENTED;
@@ -547,7 +551,7 @@ dwarf_init_info(Dwarf_Debug dbg, Dwarf_Error *error)
Dwarf_Attribute at;
Dwarf_Die die;
uint64_t abnum;
- uint64_t die_offset = offset;;
+ uint64_t die_offset = offset;
abnum = dwarf_read_uleb128(&d, &offset);
diff --git a/lib/libedit/editline.3 b/lib/libedit/editline.3
index dd4c874..fe58321 100644
--- a/lib/libedit/editline.3
+++ b/lib/libedit/editline.3
@@ -162,6 +162,11 @@ is modified to contain the number of characters read.
Returns the line read if successful, or
.Dv NULL
if no characters were read or if an error occurred.
+If an error occurred,
+.Fa count
+is set to \-1 and
+.Dv errno
+contains the error code that caused it.
The return value may not remain valid across calls to
.Fn el_gets
and must be copied if the data is to be retained.
diff --git a/lib/libedit/el.c b/lib/libedit/el.c
index 8dcd698..d6cfb2d 100644
--- a/lib/libedit/el.c
+++ b/lib/libedit/el.c
@@ -473,30 +473,6 @@ el_get(EditLine *el, int op, ...)
return (rv);
}
-/* el_data_get():
- * Set user private data.
- */
-public void
-el_data_set (el, data)
- EditLine *el;
- void *data;
-{
- el->el_data = data;
-
- return;
-}
-
-/* el_data_get():
- * Return user private data.
- */
-public void *
-el_data_get (el)
- EditLine *el;
-{
- if (el->el_data)
- return (el->el_data);
- return (NULL);
-}
/* el_line():
* Return editing info
diff --git a/lib/libedit/el.h b/lib/libedit/el.h
index 8d0d152..67d01ff 100644
--- a/lib/libedit/el.h
+++ b/lib/libedit/el.h
@@ -115,6 +115,7 @@ struct editline {
FILE *el_errfile; /* Stdio stuff */
int el_infd; /* Input file descriptor */
int el_flags; /* Various flags. */
+ int el_errno; /* Local copy of errno */
coord_t el_cursor; /* Cursor location */
char **el_display; /* Real screen image = what is there */
char **el_vdisplay; /* Virtual screen image = what we see */
diff --git a/lib/libedit/histedit.h b/lib/libedit/histedit.h
index 24af1d5..8a6caf9 100644
--- a/lib/libedit/histedit.h
+++ b/lib/libedit/histedit.h
@@ -154,13 +154,6 @@ int el_source(EditLine *, const char *);
*/
void el_resize(EditLine *);
-
-/*
- * Set user private data.
- */
-void el_data_set(EditLine *, void *);
-void * el_data_get(EditLine *);
-
/*
* User-defined function interface.
*/
diff --git a/lib/libedit/makelist b/lib/libedit/makelist
index e44a0e7..6bb2476 100644
--- a/lib/libedit/makelist
+++ b/lib/libedit/makelist
@@ -1,5 +1,5 @@
#!/bin/sh -
-# $NetBSD: makelist,v 1.10 2005/08/08 14:04:49 christos Exp $
+# $NetBSD: makelist,v 1.11 2005/10/22 16:45:03 christos Exp $
# $FreeBSD$
#
# Copyright (c) 1992, 1993
@@ -141,7 +141,7 @@ case $FLAG in
#
-fh)
cat $FILES | $AWK '/el_action_t/ { print $3 }' | \
- sort | LC_ALL=C tr 'a-z' 'A-Z' | $AWK '
+ sort | LC_ALL=C tr '[:lower:]' '[:upper:]' | $AWK '
BEGIN {
printf("/* Automatically generated file, do not edit */\n");
printf("#ifndef _h_fcns_c\n#define _h_fcns_c\n");
diff --git a/lib/libedit/read.c b/lib/libedit/read.c
index ea40e50..f0b5ef3 100644
--- a/lib/libedit/read.c
+++ b/lib/libedit/read.c
@@ -235,9 +235,12 @@ read_getcmd(EditLine *el, el_action_t *cmdnum, char *ch)
el_action_t cmd;
int num;
+ el->el_errno = 0;
do {
- if ((num = el_getc(el, ch)) != 1) /* if EOF or error */
+ if ((num = el_getc(el, ch)) != 1) { /* if EOF or error */
+ el->el_errno = num == 0 ? 0 : errno;
return (num);
+ }
#ifdef KANJI
if ((*ch & 0200)) {
@@ -289,14 +292,21 @@ read_char(EditLine *el, char *cp)
ssize_t num_read;
int tried = 0;
- while ((num_read = read(el->el_infd, cp, 1)) == -1)
+ again:
+ el->el_signal->sig_no = 0;
+ while ((num_read = read(el->el_infd, cp, 1)) == -1) {
+ if (el->el_signal->sig_no == SIGCONT) {
+ sig_set(el);
+ el_set(el, EL_REFRESH);
+ goto again;
+ }
if (!tried && read__fixio(el->el_infd, errno) == 0)
tried = 1;
else {
*cp = '\0';
return (-1);
}
-
+ }
return (int)num_read;
}
@@ -403,17 +413,20 @@ el_gets(EditLine *el, int *nread)
int num; /* how many chars we have read at NL */
char ch;
int crlf = 0;
+ int nrb;
#ifdef FIONREAD
c_macro_t *ma = &el->el_chared.c_macro;
#endif /* FIONREAD */
+ if (nread == NULL)
+ nread = &nrb;
*nread = 0;
if (el->el_flags & NO_TTY) {
char *cp = el->el_line.buffer;
size_t idx;
- while ((*el->el_read.read_char)(el, cp) == 1) {
+ while ((num = (*el->el_read.read_char)(el, cp)) == 1) {
/* make sure there is space for next character */
if (cp + 1 >= el->el_line.limit) {
idx = (cp - el->el_line.buffer);
@@ -427,12 +440,13 @@ el_gets(EditLine *el, int *nread)
if (cp[-1] == '\r' || cp[-1] == '\n')
break;
}
+ if (num == -1)
+ el->el_errno = errno;
el->el_line.cursor = el->el_line.lastchar = cp;
*cp = '\0';
- if (nread)
- *nread = (int)(el->el_line.cursor - el->el_line.buffer);
- return (*nread ? el->el_line.buffer : NULL);
+ *nread = (int)(el->el_line.cursor - el->el_line.buffer);
+ goto done;
}
@@ -443,8 +457,8 @@ el_gets(EditLine *el, int *nread)
(void) ioctl(el->el_infd, FIONREAD, (ioctl_t) & chrs);
if (chrs == 0) {
if (tty_rawmode(el) < 0) {
- if (nread)
- *nread = 0;
+ errno = 0;
+ *nread = 0;
return (NULL);
}
}
@@ -457,6 +471,7 @@ el_gets(EditLine *el, int *nread)
if (el->el_flags & EDIT_DISABLED) {
char *cp;
size_t idx;
+
if ((el->el_flags & UNBUFFERED) == 0)
cp = el->el_line.buffer;
else
@@ -464,7 +479,7 @@ el_gets(EditLine *el, int *nread)
term__flush(el);
- while ((*el->el_read.read_char)(el, cp) == 1) {
+ while ((num = (*el->el_read.read_char)(el, cp)) == 1) {
/* make sure there is space next character */
if (cp + 1 >= el->el_line.limit) {
idx = (cp - el->el_line.buffer);
@@ -480,11 +495,13 @@ el_gets(EditLine *el, int *nread)
break;
}
+ if (num == -1) {
+ el->el_errno = errno;
+ }
+
el->el_line.cursor = el->el_line.lastchar = cp;
*cp = '\0';
- if (nread)
- *nread = (int)(el->el_line.cursor - el->el_line.buffer);
- return (*nread ? el->el_line.buffer : NULL);
+ goto done;
}
for (num = OKCMD; num == OKCMD;) { /* while still editing this
@@ -617,12 +634,17 @@ el_gets(EditLine *el, int *nread)
/* make sure the tty is set up correctly */
if ((el->el_flags & UNBUFFERED) == 0) {
read_finish(el);
- if (nread)
- *nread = num;
+ *nread = num != -1 ? num : 0;
} else {
- if (nread)
- *nread =
- (int)(el->el_line.lastchar - el->el_line.buffer);
+ *nread = (int)(el->el_line.lastchar - el->el_line.buffer);
}
- return (num ? el->el_line.buffer : NULL);
+done:
+ if (*nread == 0) {
+ if (num == -1) {
+ *nread = -1;
+ errno = el->el_errno;
+ }
+ return NULL;
+ } else
+ return el->el_line.buffer;
}
diff --git a/lib/libedit/sig.c b/lib/libedit/sig.c
index 218a32e..e48dbef 100644
--- a/lib/libedit/sig.c
+++ b/lib/libedit/sig.c
@@ -29,7 +29,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $NetBSD: sig.c,v 1.14 2009/02/18 15:04:40 christos Exp $
+ * $NetBSD: sig.c,v 1.15 2009/02/19 15:20:22 christos Exp $
*/
#if !defined(lint) && !defined(SCCSID)
@@ -73,6 +73,8 @@ sig_handler(int signo)
(void) sigaddset(&nset, signo);
(void) sigprocmask(SIG_BLOCK, &nset, &oset);
+ sel->el_signal->sig_no = signo;
+
switch (signo) {
case SIGCONT:
tty_rawmode(sel);
@@ -158,12 +160,12 @@ sig_set(EditLine *el)
struct sigaction osa, nsa;
nsa.sa_handler = sig_handler;
+ nsa.sa_flags = 0;
sigemptyset(&nsa.sa_mask);
(void) sigprocmask(SIG_BLOCK, &el->el_signal->sig_set, &oset);
for (i = 0; sighdl[i] != -1; i++) {
- nsa.sa_flags = SIGINT ? 0 : SA_RESTART;
/* This could happen if we get interrupted */
if (sigaction(sighdl[i], &nsa, &osa) != -1 &&
osa.sa_handler != sig_handler)
diff --git a/lib/libedit/sig.h b/lib/libedit/sig.h
index 8773ddc..7e38100 100644
--- a/lib/libedit/sig.h
+++ b/lib/libedit/sig.h
@@ -30,7 +30,7 @@
* SUCH DAMAGE.
*
* @(#)sig.h 8.1 (Berkeley) 6/4/93
- * $NetBSD: sig.h,v 1.7 2009/02/15 21:25:01 christos Exp $
+ * $NetBSD: sig.h,v 1.8 2009/02/19 15:20:22 christos Exp $
* $FreeBSD$
*/
@@ -61,6 +61,7 @@
typedef struct {
struct sigaction sig_action[ALLSIGSNO];
sigset_t sig_set;
+ volatile sig_atomic_t sig_no;
} *el_signal_t;
protected void sig_end(EditLine*);
diff --git a/lib/libedit/term.c b/lib/libedit/term.c
index 4899193..e526484 100644
--- a/lib/libedit/term.c
+++ b/lib/libedit/term.c
@@ -340,8 +340,8 @@ term_init(EditLine *el)
if (el->el_term.t_val == NULL)
return (-1);
(void) memset(el->el_term.t_val, 0, T_val * sizeof(int));
- term_init_arrow(el);
(void) term_set(el, NULL);
+ term_init_arrow(el);
return (0);
}
diff --git a/lib/libedit/tokenizer.c b/lib/libedit/tokenizer.c
index 8e3100d..41284e8 100644
--- a/lib/libedit/tokenizer.c
+++ b/lib/libedit/tokenizer.c
@@ -29,7 +29,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $NetBSD: tokenizer.c,v 1.14 2003/12/05 13:37:48 lukem Exp $
+ * $NetBSD: tokenizer.c,v 1.15 2009/02/15 21:55:23 christos Exp $
*/
#if !defined(lint) && !defined(SCCSID)
@@ -198,7 +198,7 @@ tok_line(Tokenizer *tok, const LineInfo *line,
ptr = "";
if (ptr == line->cursor) {
cc = tok->argc;
- co = tok->wptr - tok->wstart;
+ co = (int)(tok->wptr - tok->wstart);
}
switch (*ptr) {
case '\'':
@@ -417,7 +417,7 @@ tok_line(Tokenizer *tok, const LineInfo *line,
tok_line_outok:
if (cc == -1 && co == -1) {
cc = tok->argc;
- co = tok->wptr - tok->wstart;
+ co = (int)(tok->wptr - tok->wstart);
}
if (cursorc != NULL)
*cursorc = cc;
diff --git a/lib/libelf/Makefile b/lib/libelf/Makefile
index ee96812..f4baf14 100644
--- a/lib/libelf/Makefile
+++ b/lib/libelf/Makefile
@@ -68,11 +68,9 @@ CLEANFILES= ${GENSRCS}
CLEANDIRS= sys
CFLAGS+= -I${.CURDIR} -I.
-sys/elf32.h sys/elf64.h sys/elf_common.h: sys
- ln -sf ${.CURDIR}/../../sys/${.TARGET} ${.TARGET}
-
-sys:
+sys/elf32.h sys/elf64.h sys/elf_common.h: ${.CURDIR}/../../sys/${.TARGET}
mkdir -p ${.OBJDIR}/sys
+ ln -sf ${.CURDIR}/../../sys/${.TARGET} ${.TARGET}
SHLIB_MAJOR= 1
diff --git a/lib/libelf/elf_errmsg.c b/lib/libelf/elf_errmsg.c
index 05947a7..193a602 100644
--- a/lib/libelf/elf_errmsg.c
+++ b/lib/libelf/elf_errmsg.c
@@ -36,7 +36,7 @@ __FBSDID("$FreeBSD$");
* Retrieve a human readable translation for an error message.
*/
-const char *_libelf_errors[] = {
+static const char *_libelf_errors[] = {
#define DEFINE_ERROR(N,S) [ELF_E_##N] = S
DEFINE_ERROR(NONE, "No Error"),
DEFINE_ERROR(ARCHIVE, "Malformed ar(1) archive"),
diff --git a/lib/libfetch/Makefile b/lib/libfetch/Makefile
index 7b29aa2..085aba2 100644
--- a/lib/libfetch/Makefile
+++ b/lib/libfetch/Makefile
@@ -16,8 +16,8 @@ CFLAGS+= -DINET6
.if ${MK_OPENSSL} != "no"
CFLAGS+= -DWITH_SSL
-DPADD= ${LIBSSL} ${LIBCRYPTO} ${LIBMD}
-LDADD= -lssl -lcrypto -lmd
+DPADD= ${LIBSSL} ${LIBCRYPTO}
+LDADD= -lssl -lcrypto
.else
DPADD= ${LIBMD}
LDADD= -lmd
diff --git a/lib/libfetch/common.h b/lib/libfetch/common.h
index 241dbbf..fe591d3 100644
--- a/lib/libfetch/common.h
+++ b/lib/libfetch/common.h
@@ -63,7 +63,7 @@ struct fetchconn {
SSL *ssl; /* SSL handle */
SSL_CTX *ssl_ctx; /* SSL context */
X509 *ssl_cert; /* server certificate */
- SSL_METHOD *ssl_meth; /* SSL method */
+ const SSL_METHOD *ssl_meth; /* SSL method */
#endif
int ref; /* reference count */
};
diff --git a/lib/libfetch/file.c b/lib/libfetch/file.c
index 8569ff3..8c1d404 100644
--- a/lib/libfetch/file.c
+++ b/lib/libfetch/file.c
@@ -50,12 +50,15 @@ fetchXGetFile(struct url *u, struct url_stat *us, const char *flags)
f = fopen(u->doc, "r");
- if (f == NULL)
+ if (f == NULL) {
fetch_syserr();
+ return (NULL);
+ }
if (u->offset && fseeko(f, u->offset, SEEK_SET) == -1) {
fclose(f);
fetch_syserr();
+ return (NULL);
}
fcntl(fileno(f), F_SETFD, FD_CLOEXEC);
@@ -78,12 +81,15 @@ fetchPutFile(struct url *u, const char *flags)
else
f = fopen(u->doc, "w+");
- if (f == NULL)
+ if (f == NULL) {
fetch_syserr();
+ return (NULL);
+ }
if (u->offset && fseeko(f, u->offset, SEEK_SET) == -1) {
fclose(f);
fetch_syserr();
+ return (NULL);
}
fcntl(fileno(f), F_SETFD, FD_CLOEXEC);
diff --git a/lib/libfetch/http.c b/lib/libfetch/http.c
index f6e063a..00dd887 100644
--- a/lib/libfetch/http.c
+++ b/lib/libfetch/http.c
@@ -76,7 +76,15 @@ __FBSDID("$FreeBSD$");
#include <string.h>
#include <time.h>
#include <unistd.h>
+
+#ifdef WITH_SSL
+#include <openssl/md5.h>
+#define MD5Init(c) MD5_Init(c)
+#define MD5Update(c, data, len) MD5_Update(c, data, len)
+#define MD5Final(md, c) MD5_Final(md, c)
+#else
#include <md5.h>
+#endif
#include <netinet/in.h>
#include <netinet/tcp.h>
@@ -86,7 +94,7 @@ __FBSDID("$FreeBSD$");
#include "httperr.h"
/* Maximum number of redirects to follow */
-#define MAX_REDIRECT 5
+#define MAX_REDIRECT 20
/* Symbolic names for reply codes we care about */
#define HTTP_OK 200
@@ -95,7 +103,9 @@ __FBSDID("$FreeBSD$");
#define HTTP_MOVED_TEMP 302
#define HTTP_SEE_OTHER 303
#define HTTP_NOT_MODIFIED 304
+#define HTTP_USE_PROXY 305
#define HTTP_TEMP_REDIRECT 307
+#define HTTP_PERM_REDIRECT 308
#define HTTP_NEED_AUTH 401
#define HTTP_NEED_PROXY_AUTH 407
#define HTTP_BAD_RANGE 416
@@ -104,6 +114,7 @@ __FBSDID("$FreeBSD$");
#define HTTP_REDIRECT(xyz) ((xyz) == HTTP_MOVED_PERM \
|| (xyz) == HTTP_MOVED_TEMP \
|| (xyz) == HTTP_TEMP_REDIRECT \
+ || (xyz) == HTTP_USE_PROXY \
|| (xyz) == HTTP_SEE_OTHER)
#define HTTP_ERROR(xyz) ((xyz) > 400 && (xyz) < 599)
@@ -1516,8 +1527,7 @@ http_request(struct url *URL, const char *op, struct url_stat *us,
/* try the provided URL first */
url = URL;
- /* if the A flag is set, we only get one try */
- n = noredirect ? 1 : MAX_REDIRECT;
+ n = MAX_REDIRECT;
i = 0;
e = HTTP_PROTOCOL_ERROR;
@@ -1689,6 +1699,7 @@ http_request(struct url *URL, const char *op, struct url_stat *us,
case HTTP_MOVED_PERM:
case HTTP_MOVED_TEMP:
case HTTP_SEE_OTHER:
+ case HTTP_USE_PROXY:
/*
* Not so fine, but we still have to read the
* headers to get the new location.
@@ -1764,6 +1775,17 @@ http_request(struct url *URL, const char *op, struct url_stat *us,
case hdr_location:
if (!HTTP_REDIRECT(conn->err))
break;
+ /*
+ * if the A flag is set, we don't follow
+ * temporary redirects.
+ */
+ if (noredirect &&
+ conn->err != HTTP_MOVED_PERM &&
+ conn->err != HTTP_PERM_REDIRECT &&
+ conn->err != HTTP_USE_PROXY) {
+ n = 1;
+ break;
+ }
if (new)
free(new);
if (verbose)
diff --git a/lib/libfetch/http.errors b/lib/libfetch/http.errors
index 1f38574..e5389fe 100644
--- a/lib/libfetch/http.errors
+++ b/lib/libfetch/http.errors
@@ -18,6 +18,7 @@
304 OK Not Modified
305 INFO Use Proxy
307 MOVED Temporary Redirect
+308 MOVED Permanent Redirect
400 PROTO Bad Request
401 AUTH Unauthorized
402 AUTH Payment Required
diff --git a/lib/libgeom/geom_xml2tree.c b/lib/libgeom/geom_xml2tree.c
index 24315cd..02be019 100644
--- a/lib/libgeom/geom_xml2tree.c
+++ b/lib/libgeom/geom_xml2tree.c
@@ -56,6 +56,8 @@ struct mystate {
struct sbuf *sbuf[20];
struct gconf *config;
int nident;
+ XML_Parser parser;
+ int error;
};
static void
@@ -85,6 +87,8 @@ StartElement(void *userData, const char *name, const char **attr)
if (!strcmp(name, "class") && mt->class == NULL) {
mt->class = calloc(1, sizeof *mt->class);
if (mt->class == NULL) {
+ mt->error = errno;
+ XML_StopParser(mt->parser, 0);
warn("Cannot allocate memory during processing of '%s' "
"element", name);
return;
@@ -98,6 +102,8 @@ StartElement(void *userData, const char *name, const char **attr)
if (!strcmp(name, "geom") && mt->geom == NULL) {
mt->geom = calloc(1, sizeof *mt->geom);
if (mt->geom == NULL) {
+ mt->error = errno;
+ XML_StopParser(mt->parser, 0);
warn("Cannot allocate memory during processing of '%s' "
"element", name);
return;
@@ -116,6 +122,8 @@ StartElement(void *userData, const char *name, const char **attr)
if (!strcmp(name, "consumer") && mt->consumer == NULL) {
mt->consumer = calloc(1, sizeof *mt->consumer);
if (mt->consumer == NULL) {
+ mt->error = errno;
+ XML_StopParser(mt->parser, 0);
warn("Cannot allocate memory during processing of '%s' "
"element", name);
return;
@@ -137,6 +145,8 @@ StartElement(void *userData, const char *name, const char **attr)
if (!strcmp(name, "provider") && mt->provider == NULL) {
mt->provider = calloc(1, sizeof *mt->provider);
if (mt->provider == NULL) {
+ mt->error = errno;
+ XML_StopParser(mt->parser, 0);
warn("Cannot allocate memory during processing of '%s' "
"element", name);
return;
@@ -180,16 +190,19 @@ EndElement(void *userData, const char *name)
char *p;
mt = userData;
- sbuf_finish(mt->sbuf[mt->level]);
- p = strdup(sbuf_data(mt->sbuf[mt->level]));
+ p = NULL;
+ if (sbuf_finish(mt->sbuf[mt->level]) == 0)
+ p = strdup(sbuf_data(mt->sbuf[mt->level]));
+ sbuf_delete(mt->sbuf[mt->level]);
+ mt->sbuf[mt->level] = NULL;
+ mt->level--;
if (p == NULL) {
+ mt->error = errno;
+ XML_StopParser(mt->parser, 0);
warn("Cannot allocate memory during processing of '%s' "
"element", name);
return;
}
- sbuf_delete(mt->sbuf[mt->level]);
- mt->sbuf[mt->level] = NULL;
- mt->level--;
if (strlen(p) == 0) {
free(p);
p = NULL;
@@ -249,12 +262,16 @@ EndElement(void *userData, const char *name)
if (mt->config != NULL) {
gc = calloc(1, sizeof *gc);
if (gc == NULL) {
+ mt->error = errno;
+ XML_StopParser(mt->parser, 0);
warn("Cannot allocate memory during processing of '%s' "
"element", name);
return;
}
gc->lg_name = strdup(name);
if (gc->lg_name == NULL) {
+ mt->error = errno;
+ XML_StopParser(mt->parser, 0);
warn("Cannot allocate memory during processing of '%s' "
"element", name);
return;
@@ -334,7 +351,7 @@ geom_xml2tree(struct gmesh *gmp, char *p)
struct ggeom *ge;
struct gprovider *pr;
struct gconsumer *co;
- int i;
+ int error, i;
memset(gmp, 0, sizeof *gmp);
LIST_INIT(&gmp->lg_class);
@@ -347,14 +364,22 @@ geom_xml2tree(struct gmesh *gmp, char *p)
return (ENOMEM);
}
mt->mesh = gmp;
+ mt->parser = parser;
+ error = 0;
XML_SetUserData(parser, mt);
XML_SetElementHandler(parser, StartElement, EndElement);
XML_SetCharacterDataHandler(parser, CharData);
i = XML_Parse(parser, p, strlen(p), 1);
+ if (mt->error != 0)
+ error = mt->error;
+ else if (i != 1) {
+ error = XML_GetErrorCode(parser) == XML_ERROR_NO_MEMORY ?
+ ENOMEM : EILSEQ;
+ }
XML_ParserFree(parser);
- if (i != 1) {
+ if (error != 0) {
free(mt);
- return (-1);
+ return (error);
}
gmp->lg_ident = calloc(sizeof *gmp->lg_ident, mt->nident + 1);
free(mt);
diff --git a/lib/libjail/jail.c b/lib/libjail/jail.c
index 5cd2ad2..207b9f2 100644
--- a/lib/libjail/jail.c
+++ b/lib/libjail/jail.c
@@ -85,19 +85,22 @@ jail_setv(int flags, ...)
(void)va_arg(tap, char *);
va_end(tap);
jp = alloca(njp * sizeof(struct jailparam));
- for (njp = 0; (name = va_arg(ap, char *)) != NULL; njp++) {
+ for (njp = 0; (name = va_arg(ap, char *)) != NULL;) {
value = va_arg(ap, char *);
- if (jailparam_init(jp + njp, name) < 0 ||
- jailparam_import(jp + njp, value) < 0) {
- jailparam_free(jp, njp);
- va_end(ap);
- return (-1);
- }
+ if (jailparam_init(jp + njp, name) < 0)
+ goto error;
+ if (jailparam_import(jp + njp++, value) < 0)
+ goto error;
}
va_end(ap);
jid = jailparam_set(jp, njp, flags);
jailparam_free(jp, njp);
return (jid);
+
+ error:
+ jailparam_free(jp, njp);
+ va_end(ap);
+ return (-1);
}
/*
@@ -195,7 +198,7 @@ jail_getv(int flags, ...)
int
jailparam_all(struct jailparam **jpp)
{
- struct jailparam *jp;
+ struct jailparam *jp, *tjp;
size_t mlen1, mlen2, buflen;
int njp, nlist;
int mib1[CTL_MAXNAME], mib2[CTL_MAXNAME - 2];
@@ -242,11 +245,10 @@ jailparam_all(struct jailparam **jpp)
/* Add the parameter to the list */
if (njp >= nlist) {
nlist *= 2;
- jp = realloc(jp, nlist * sizeof(*jp));
- if (jp == NULL) {
- jailparam_free(jp, njp);
- return (-1);
- }
+ tjp = realloc(jp, nlist * sizeof(*jp));
+ if (tjp == NULL)
+ goto error;
+ jp = tjp;
}
if (jailparam_init(jp + njp, buf + sizeof(SJPARAM)) < 0)
goto error;
@@ -277,6 +279,8 @@ jailparam_init(struct jailparam *jp, const char *name)
}
if (jailparam_type(jp) < 0) {
jailparam_free(jp, 1);
+ jp->jp_name = NULL;
+ jp->jp_value = NULL;
return (-1);
}
return (0);
diff --git a/lib/libkvm/kvm_i386.c b/lib/libkvm/kvm_i386.c
index a92979f..601126b 100644
--- a/lib/libkvm/kvm_i386.c
+++ b/lib/libkvm/kvm_i386.c
@@ -238,7 +238,6 @@ _kvm_initvtop(kvm_t *kd)
return (-1);
}
kd->vmst->PTD = PTD;
- return (0);
kd->vmst->pae = 0;
}
return (0);
diff --git a/lib/libkvm/kvm_proc.c b/lib/libkvm/kvm_proc.c
index 8fc415c..31258d7 100644
--- a/lib/libkvm/kvm_proc.c
+++ b/lib/libkvm/kvm_proc.c
@@ -144,6 +144,8 @@ kvm_proclist(kvm_t *kd, int what, int arg, struct proc *p,
_kvm_err(kd, kd->program, "can't read proc at %p", p);
return (-1);
}
+ if (proc.p_state == PRS_NEW)
+ continue;
if (proc.p_state != PRS_ZOMBIE) {
if (KREAD(kd, (u_long)TAILQ_FIRST(&proc.p_threads),
&mtd)) {
@@ -591,9 +593,15 @@ liveout:
nprocs = kvm_deadprocs(kd, op, arg, nl[1].n_value,
nl[2].n_value, nprocs);
+ if (nprocs <= 0) {
+ _kvm_freeprocs(kd);
+ nprocs = 0;
+ }
#ifdef notdef
- size = nprocs * sizeof(struct kinfo_proc);
- (void)realloc(kd->procbase, size);
+ else {
+ size = nprocs * sizeof(struct kinfo_proc);
+ kd->procbase = realloc(kd->procbase, size);
+ }
#endif
}
*cnt = nprocs;
diff --git a/lib/libmagic/Makefile b/lib/libmagic/Makefile
index fbf71ef..d341a3a 100644
--- a/lib/libmagic/Makefile
+++ b/lib/libmagic/Makefile
@@ -39,9 +39,9 @@ magic.mgc: mkmagic magic
CLEANFILES+= mkmagic
build-tools: mkmagic
-mkmagic: apprentice.c funcs.c getline.c magic.c print.c
- ${CC} ${CFLAGS} -DCOMPILE_ONLY -DHOSTPROG ${LDFLAGS} \
- -o ${.TARGET} ${.ALLSRC}
+mkmagic: apprentice.c encoding.c funcs.c magic.c print.c
+ ${CC} ${CFLAGS} -DCOMPILE_ONLY ${LDFLAGS} -o ${.TARGET} ${.ALLSRC} \
+ ${LDADD}
FILEVER!= awk '$$1 == "\#define" && $$2 == "VERSION" { print $$3; exit }' \
${.CURDIR}/config.h
diff --git a/lib/libmagic/config.h b/lib/libmagic/config.h
index c17883f..c7e38ec 100644
--- a/lib/libmagic/config.h
+++ b/lib/libmagic/config.h
@@ -39,9 +39,7 @@
#define HAVE_FSEEKO 1
/* Define to 1 if you have the `getline' function. */
-#ifndef HOSTPROG
#define HAVE_GETLINE 1
-#endif
/* Define to 1 if you have the <getopt.h> header file. */
#define HAVE_GETOPT_H 1
diff --git a/lib/libmandoc/Makefile b/lib/libmandoc/Makefile
new file mode 100644
index 0000000..9fca07e
--- /dev/null
+++ b/lib/libmandoc/Makefile
@@ -0,0 +1,20 @@
+# $FreeBSD$
+
+MDOCMLDIR= ${.CURDIR}/../../contrib/mdocml
+.PATH: ${MDOCMLDIR}
+
+LIB= mandoc
+#NO_PIC=
+INTERNALLIB=
+MAN= mandoc.3
+SRCS= arch.c att.c chars.c \
+ compat_fgetln.c compat_getsubopt.c compat_strlcat.c compat_strlcpy.c \
+ eqn.c lib.c man.c man_hash.c man_macro.c man_validate.c mandoc.c \
+ mdoc.c mdoc_argv.c mdoc_hash.c mdoc_macro.c mdoc_validate.c \
+ msec.c read.c roff.c st.c \
+ tbl.c tbl_data.c tbl_layout.c tbl_opts.c vol.c
+
+WARNS?= 3
+CFLAGS+= -DHAVE_CONFIG_H -DVERSION="\"1.12.1\""
+
+.include <bsd.lib.mk>
diff --git a/lib/libmemstat/memstat_uma.c b/lib/libmemstat/memstat_uma.c
index 35f6dad..040198c 100644
--- a/lib/libmemstat/memstat_uma.c
+++ b/lib/libmemstat/memstat_uma.c
@@ -254,7 +254,7 @@ kread(kvm_t *kvm, void *kvm_pointer, void *address, size_t size,
}
static int
-kread_string(kvm_t *kvm, void *kvm_pointer, char *buffer, int buflen)
+kread_string(kvm_t *kvm, const void *kvm_pointer, char *buffer, int buflen)
{
ssize_t ret;
int i;
diff --git a/lib/libpam/modules/pam_krb5/pam_krb5.c b/lib/libpam/modules/pam_krb5/pam_krb5.c
index 602718f..19592e3 100644
--- a/lib/libpam/modules/pam_krb5/pam_krb5.c
+++ b/lib/libpam/modules/pam_krb5/pam_krb5.c
@@ -91,6 +91,7 @@ static void compat_free_data_contents(krb5_context, krb5_data *);
#define PAM_OPT_NO_CCACHE "no_ccache"
#define PAM_OPT_NO_USER_CHECK "no_user_check"
#define PAM_OPT_REUSE_CCACHE "reuse_ccache"
+#define PAM_OPT_NO_USER_CHECK "no_user_check"
#define PAM_LOG_KRB5_ERR(ctx, rv, fmt, ...) \
do { \
@@ -218,10 +219,12 @@ pam_sm_authenticate(pam_handle_t *pamh, int flags __unused,
PAM_LOG("PAM_USER Redone");
}
- pwd = getpwnam(user);
- if (pwd == NULL) {
- retval = PAM_USER_UNKNOWN;
- goto cleanup2;
+ if (!openpam_get_option(pamh, PAM_OPT_NO_USER_CHECK)) {
+ pwd = getpwnam(user);
+ if (pwd == NULL) {
+ retval = PAM_USER_UNKNOWN;
+ goto cleanup2;
+ }
}
PAM_LOG("Done getpwnam()");
@@ -335,11 +338,11 @@ cleanup:
PAM_LOG("Done cleanup");
cleanup2:
krb5_free_principal(pam_context, princ);
- PAM_LOG("Done cleanup2");
-cleanup3:
if (princ_name)
free(princ_name);
+ PAM_LOG("Done cleanup2");
+cleanup3:
krb5_free_context(pam_context);
PAM_LOG("Done cleanup3");
@@ -647,7 +650,7 @@ pam_sm_acct_mgmt(pam_handle_t *pamh, int flags __unused,
if (krbret != 0) {
PAM_LOG_KRB5_ERR(pam_context, krbret,
"Error krb5_cc_get_principal()");
- retval = PAM_PERM_DENIED;;
+ retval = PAM_PERM_DENIED;
goto cleanup;
}
@@ -802,11 +805,11 @@ cleanup:
PAM_LOG("Done cleanup");
cleanup2:
krb5_free_principal(pam_context, princ);
- PAM_LOG("Done cleanup2");
-cleanup3:
if (princ_name)
free(princ_name);
+ PAM_LOG("Done cleanup2");
+cleanup3:
krb5_free_context(pam_context);
PAM_LOG("Done cleanup3");
diff --git a/lib/libpam/modules/pam_lastlog/pam_lastlog.8 b/lib/libpam/modules/pam_lastlog/pam_lastlog.8
index 8ee5dec..cd75fff 100644
--- a/lib/libpam/modules/pam_lastlog/pam_lastlog.8
+++ b/lib/libpam/modules/pam_lastlog/pam_lastlog.8
@@ -34,7 +34,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd January 24, 2002
+.Dd January 21, 2010
.Dt PAM_LASTLOG 8
.Os
.Sh NAME
diff --git a/lib/libpam/modules/pam_radius/pam_radius.c b/lib/libpam/modules/pam_radius/pam_radius.c
index 306c4b7..c5d4dd4 100644
--- a/lib/libpam/modules/pam_radius/pam_radius.c
+++ b/lib/libpam/modules/pam_radius/pam_radius.c
@@ -38,7 +38,6 @@
__FBSDID("$FreeBSD$");
#include <sys/param.h>
-#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <pwd.h>
diff --git a/lib/libpam/modules/pam_unix/pam_unix.c b/lib/libpam/modules/pam_unix/pam_unix.c
index 415004a..5881ecf 100644
--- a/lib/libpam/modules/pam_unix/pam_unix.c
+++ b/lib/libpam/modules/pam_unix/pam_unix.c
@@ -94,13 +94,13 @@ pam_sm_authenticate(pam_handle_t *pamh, int flags __unused,
const char *pass, *user, *realpw, *prompt;
if (openpam_get_option(pamh, PAM_OPT_AUTH_AS_SELF)) {
- pwd = getpwnam(getlogin());
+ user = getlogin();
} else {
retval = pam_get_user(pamh, &user, NULL);
if (retval != PAM_SUCCESS)
return (retval);
- pwd = getpwnam(user);
}
+ pwd = getpwnam(user);
PAM_LOG("Got user: %s", user);
diff --git a/lib/libpcap/config.h b/lib/libpcap/config.h
index b364c13..379772b 100644
--- a/lib/libpcap/config.h
+++ b/lib/libpcap/config.h
@@ -221,7 +221,7 @@
/* #undef NETINET_ETHER_H_DECLARES_ETHER_HOSTTON */
/* Define to 1 if netinet/if_ether.h declares `ether_hostton' */
-#define NETINET_IF_ETHER_H_DECLARES_ETHER_HOSTTON
+#define NETINET_IF_ETHER_H_DECLARES_ETHER_HOSTTON /**/
/* do not use protochain */
/* #undef NO_PROTOCHAIN */
@@ -238,6 +238,9 @@
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME ""
+/* Define to the home page for this package. */
+#define PACKAGE_URL ""
+
/* Define to the version of this package. */
#define PACKAGE_VERSION ""
@@ -250,6 +253,9 @@
/* target host supports CAN sniffing */
/* #undef PCAP_SUPPORT_CAN */
+/* target host supports canusb */
+/* #undef PCAP_SUPPORT_CANUSB */
+
/* target host supports netfilter sniffing */
/* #undef PCAP_SUPPORT_NETFILTER */
diff --git a/lib/libpmc/Makefile b/lib/libpmc/Makefile
index 5edbfe6..f59dc2b 100644
--- a/lib/libpmc/Makefile
+++ b/lib/libpmc/Makefile
@@ -28,6 +28,7 @@ MAN+= pmc.atom.3
MAN+= pmc.core.3
MAN+= pmc.core2.3
MAN+= pmc.iaf.3
+MAN+= pmc.ivybridge.3
MAN+= pmc.ucf.3
MAN+= pmc.k7.3
MAN+= pmc.k8.3
@@ -38,10 +39,11 @@ MAN+= pmc.corei7.3
MAN+= pmc.corei7uc.3
MAN+= pmc.sandybridge.3
MAN+= pmc.sandybridgeuc.3
+MAN+= pmc.sandybridgexeon.3
MAN+= pmc.westmere.3
MAN+= pmc.westmereuc.3
MAN+= pmc.tsc.3
-.elif ${MACHINE_CPUARCH} == "arm" && ${CPUTYPE} == "xscale"
+.elif ${MACHINE_CPUARCH} == "arm"
MAN+= pmc.xscale.3
.elif ${MACHINE_CPUARCH} == "mips"
MAN+= pmc.mips24k.3
diff --git a/lib/libpmc/libpmc.c b/lib/libpmc/libpmc.c
index 3b7dc37..4fb2572 100644
--- a/lib/libpmc/libpmc.c
+++ b/lib/libpmc/libpmc.c
@@ -183,11 +183,21 @@ static const struct pmc_event_descr corei7_event_table[] =
__PMC_EV_ALIAS_COREI7()
};
+static const struct pmc_event_descr ivybridge_event_table[] =
+{
+ __PMC_EV_ALIAS_IVYBRIDGE()
+};
+
static const struct pmc_event_descr sandybridge_event_table[] =
{
__PMC_EV_ALIAS_SANDYBRIDGE()
};
+static const struct pmc_event_descr sandybridge_xeon_event_table[] =
+{
+ __PMC_EV_ALIAS_SANDYBRIDGE_XEON()
+};
+
static const struct pmc_event_descr westmere_event_table[] =
{
__PMC_EV_ALIAS_WESTMERE()
@@ -222,7 +232,9 @@ PMC_MDEP_TABLE(atom, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC);
PMC_MDEP_TABLE(core, IAP, PMC_CLASS_SOFT, PMC_CLASS_TSC);
PMC_MDEP_TABLE(core2, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC);
PMC_MDEP_TABLE(corei7, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP);
+PMC_MDEP_TABLE(ivybridge, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC);
PMC_MDEP_TABLE(sandybridge, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP);
+PMC_MDEP_TABLE(sandybridge_xeon, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC);
PMC_MDEP_TABLE(westmere, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP);
PMC_MDEP_TABLE(k7, K7, PMC_CLASS_SOFT, PMC_CLASS_TSC);
PMC_MDEP_TABLE(k8, K8, PMC_CLASS_SOFT, PMC_CLASS_TSC);
@@ -259,7 +271,9 @@ PMC_CLASS_TABLE_DESC(atom, IAP, atom, iap);
PMC_CLASS_TABLE_DESC(core, IAP, core, iap);
PMC_CLASS_TABLE_DESC(core2, IAP, core2, iap);
PMC_CLASS_TABLE_DESC(corei7, IAP, corei7, iap);
+PMC_CLASS_TABLE_DESC(ivybridge, IAP, ivybridge, iap);
PMC_CLASS_TABLE_DESC(sandybridge, IAP, sandybridge, iap);
+PMC_CLASS_TABLE_DESC(sandybridge_xeon, IAP, sandybridge_xeon, iap);
PMC_CLASS_TABLE_DESC(westmere, IAP, westmere, iap);
PMC_CLASS_TABLE_DESC(ucf, UCF, ucf, ucf);
PMC_CLASS_TABLE_DESC(corei7uc, UCP, corei7uc, ucp);
@@ -365,14 +379,14 @@ static struct pmc_op_getdyneventinfo soft_event_info;
/* Event masks for events */
struct pmc_masks {
const char *pm_name;
- const uint32_t pm_value;
+ const uint64_t pm_value;
};
#define PMCMASK(N,V) { .pm_name = #N, .pm_value = (V) }
#define NULLMASK { .pm_name = NULL }
#if defined(__amd64__) || defined(__i386__)
static int
-pmc_parse_mask(const struct pmc_masks *pmask, char *p, uint32_t *evmask)
+pmc_parse_mask(const struct pmc_masks *pmask, char *p, uint64_t *evmask)
{
const struct pmc_masks *pm;
char *q, *r;
@@ -561,8 +575,12 @@ static struct pmc_event_alias core2_aliases_without_iaf[] = {
#define atom_aliases_without_iaf core2_aliases_without_iaf
#define corei7_aliases core2_aliases
#define corei7_aliases_without_iaf core2_aliases_without_iaf
+#define ivybridge_aliases core2_aliases
+#define ivybridge_aliases_without_iaf core2_aliases_without_iaf
#define sandybridge_aliases core2_aliases
#define sandybridge_aliases_without_iaf core2_aliases_without_iaf
+#define sandybridge_xeon_aliases core2_aliases
+#define sandybridge_xeon_aliases_without_iaf core2_aliases_without_iaf
#define westmere_aliases core2_aliases
#define westmere_aliases_without_iaf core2_aliases_without_iaf
@@ -663,7 +681,7 @@ static struct pmc_masks iap_transition_mask[] = {
NULLMASK
};
-static struct pmc_masks iap_rsp_mask[] = {
+static struct pmc_masks iap_rsp_mask_i7_wm[] = {
PMCMASK(DMND_DATA_RD, (1 << 0)),
PMCMASK(DMND_RFO, (1 << 1)),
PMCMASK(DMND_IFETCH, (1 << 2)),
@@ -682,12 +700,43 @@ static struct pmc_masks iap_rsp_mask[] = {
NULLMASK
};
+static struct pmc_masks iap_rsp_mask_sb_sbx_ib[] = {
+ PMCMASK(REQ_DMND_DATA_RD, (1ULL << 0)),
+ PMCMASK(REQ_DMND_RFO, (1ULL << 1)),
+ PMCMASK(REQ_DMND_IFETCH, (1ULL << 2)),
+ PMCMASK(REQ_WB, (1ULL << 3)),
+ PMCMASK(REQ_PF_DATA_RD, (1ULL << 4)),
+ PMCMASK(REQ_PF_RFO, (1ULL << 5)),
+ PMCMASK(REQ_PF_IFETCH, (1ULL << 6)),
+ PMCMASK(REQ_PF_LLC_DATA_RD, (1ULL << 7)),
+ PMCMASK(REQ_PF_LLC_RFO, (1ULL << 8)),
+ PMCMASK(REQ_PF_LLC_IFETCH, (1ULL << 9)),
+ PMCMASK(REQ_BUS_LOCKS, (1ULL << 10)),
+ PMCMASK(REQ_STRM_ST, (1ULL << 11)),
+ PMCMASK(REQ_OTHER, (1ULL << 15)),
+ PMCMASK(RES_ANY, (1ULL << 16)),
+ PMCMASK(RES_SUPPLIER_SUPP, (1ULL << 17)),
+ PMCMASK(RES_SUPPLIER_LLC_HITM, (1ULL << 18)),
+ PMCMASK(RES_SUPPLIER_LLC_HITE, (1ULL << 19)),
+ PMCMASK(RES_SUPPLIER_LLC_HITS, (1ULL << 20)),
+ PMCMASK(RES_SUPPLIER_LLC_HITF, (1ULL << 21)),
+ PMCMASK(RES_SUPPLIER_LOCAL, (1ULL << 22)),
+ PMCMASK(RES_SNOOP_SNP_NONE, (1ULL << 31)),
+ PMCMASK(RES_SNOOP_SNP_NO_NEEDED,(1ULL << 32)),
+ PMCMASK(RES_SNOOP_SNP_MISS, (1ULL << 33)),
+ PMCMASK(RES_SNOOP_HIT_NO_FWD, (1ULL << 34)),
+ PMCMASK(RES_SNOOP_HIT_FWD, (1ULL << 35)),
+ PMCMASK(RES_SNOOP_HITM, (1ULL << 36)),
+ PMCMASK(RES_NON_DRAM, (1ULL << 37)),
+ NULLMASK
+};
+
static int
iap_allocate_pmc(enum pmc_event pe, char *ctrspec,
struct pmc_op_pmcallocate *pmc_config)
{
char *e, *p, *q;
- uint32_t cachestate, evmask, rsp;
+ uint64_t cachestate, evmask, rsp;
int count, n;
pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE |
@@ -753,7 +802,14 @@ iap_allocate_pmc(enum pmc_event pe, char *ctrspec,
} else if (cpu_info.pm_cputype == PMC_CPU_INTEL_COREI7 ||
cpu_info.pm_cputype == PMC_CPU_INTEL_WESTMERE) {
if (KWPREFIXMATCH(p, IAP_KW_RSP "=")) {
- n = pmc_parse_mask(iap_rsp_mask, p, &rsp);
+ n = pmc_parse_mask(iap_rsp_mask_i7_wm, p, &rsp);
+ } else
+ return (-1);
+ } else if (cpu_info.pm_cputype == PMC_CPU_INTEL_SANDYBRIDGE ||
+ cpu_info.pm_cputype == PMC_CPU_INTEL_SANDYBRIDGE_XEON ||
+ cpu_info.pm_cputype == PMC_CPU_INTEL_IVYBRIDGE) {
+ if (KWPREFIXMATCH(p, IAP_KW_RSP "=")) {
+ n = pmc_parse_mask(iap_rsp_mask_sb_sbx_ib, p, &rsp);
} else
return (-1);
} else
@@ -1072,7 +1128,8 @@ k8_allocate_pmc(enum pmc_event pe, char *ctrspec,
{
char *e, *p, *q;
int n;
- uint32_t count, evmask;
+ uint32_t count;
+ uint64_t evmask;
const struct pmc_masks *pm, *pmask;
pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE);
@@ -1554,7 +1611,8 @@ p4_allocate_pmc(enum pmc_event pe, char *ctrspec,
char *e, *p, *q;
int count, has_tag, has_busreqtype, n;
- uint32_t evmask, cccractivemask;
+ uint32_t cccractivemask;
+ uint64_t evmask;
const struct pmc_masks *pm, *pmask;
pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE);
@@ -1982,7 +2040,7 @@ p6_allocate_pmc(enum pmc_event pe, char *ctrspec,
struct pmc_op_pmcallocate *pmc_config)
{
char *e, *p, *q;
- uint32_t evmask;
+ uint64_t evmask;
int count, n;
const struct pmc_masks *pm, *pmask;
@@ -2206,7 +2264,7 @@ soft_allocate_pmc(enum pmc_event pe, char *ctrspec,
(void)ctrspec;
(void)pmc_config;
- if (pe < PMC_EV_SOFT_FIRST || pe > PMC_EV_SOFT_LAST)
+ if ((int)pe < PMC_EV_SOFT_FIRST || (int)pe > PMC_EV_SOFT_LAST)
return (-1);
pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE);
@@ -2622,10 +2680,18 @@ pmc_event_names_of_class(enum pmc_class cl, const char ***eventnames,
ev = corei7_event_table;
count = PMC_EVENT_TABLE_SIZE(corei7);
break;
+ case PMC_CPU_INTEL_IVYBRIDGE:
+ ev = ivybridge_event_table;
+ count = PMC_EVENT_TABLE_SIZE(ivybridge);
+ break;
case PMC_CPU_INTEL_SANDYBRIDGE:
ev = sandybridge_event_table;
count = PMC_EVENT_TABLE_SIZE(sandybridge);
break;
+ case PMC_CPU_INTEL_SANDYBRIDGE_XEON:
+ ev = sandybridge_xeon_event_table;
+ count = PMC_EVENT_TABLE_SIZE(sandybridge_xeon);
+ break;
case PMC_CPU_INTEL_WESTMERE:
ev = westmere_event_table;
count = PMC_EVENT_TABLE_SIZE(westmere);
@@ -2914,11 +2980,17 @@ pmc_init(void)
pmc_class_table[n++] = &corei7uc_class_table_descr;
PMC_MDEP_INIT_INTEL_V2(corei7);
break;
+ case PMC_CPU_INTEL_IVYBRIDGE:
+ PMC_MDEP_INIT_INTEL_V2(ivybridge);
+ break;
case PMC_CPU_INTEL_SANDYBRIDGE:
pmc_class_table[n++] = &ucf_class_table_descr;
pmc_class_table[n++] = &sandybridgeuc_class_table_descr;
PMC_MDEP_INIT_INTEL_V2(sandybridge);
break;
+ case PMC_CPU_INTEL_SANDYBRIDGE_XEON:
+ PMC_MDEP_INIT_INTEL_V2(sandybridge_xeon);
+ break;
case PMC_CPU_INTEL_WESTMERE:
pmc_class_table[n++] = &ucf_class_table_descr;
pmc_class_table[n++] = &westmereuc_class_table_descr;
@@ -3049,10 +3121,18 @@ _pmc_name_of_event(enum pmc_event pe, enum pmc_cputype cpu)
ev = corei7_event_table;
evfence = corei7_event_table + PMC_EVENT_TABLE_SIZE(corei7);
break;
+ case PMC_CPU_INTEL_IVYBRIDGE:
+ ev = ivybridge_event_table;
+ evfence = ivybridge_event_table + PMC_EVENT_TABLE_SIZE(ivybridge);
+ break;
case PMC_CPU_INTEL_SANDYBRIDGE:
ev = sandybridge_event_table;
evfence = sandybridge_event_table + PMC_EVENT_TABLE_SIZE(sandybridge);
break;
+ case PMC_CPU_INTEL_SANDYBRIDGE_XEON:
+ ev = sandybridge_xeon_event_table;
+ evfence = sandybridge_xeon_event_table + PMC_EVENT_TABLE_SIZE(sandybridge_xeon);
+ break;
case PMC_CPU_INTEL_WESTMERE:
ev = westmere_event_table;
evfence = westmere_event_table + PMC_EVENT_TABLE_SIZE(westmere);
@@ -3110,7 +3190,7 @@ _pmc_name_of_event(enum pmc_event pe, enum pmc_cputype cpu)
} else if (pe == PMC_EV_TSC_TSC) {
ev = tsc_event_table;
evfence = tsc_event_table + PMC_EVENT_TABLE_SIZE(tsc);
- } else if (pe >= PMC_EV_SOFT_FIRST && pe <= PMC_EV_SOFT_LAST) {
+ } else if ((int)pe >= PMC_EV_SOFT_FIRST && (int)pe <= PMC_EV_SOFT_LAST) {
ev = soft_event_table;
evfence = soft_event_table + soft_event_info.pm_nevent;
}
diff --git a/lib/libpmc/pmc.ivybridge.3 b/lib/libpmc/pmc.ivybridge.3
new file mode 100644
index 0000000..9a81da4
--- /dev/null
+++ b/lib/libpmc/pmc.ivybridge.3
@@ -0,0 +1,880 @@
+.\" Copyright (c) 2012 Fabien Thomas. 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 THE AUTHOR 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 AUTHOR 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.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd October 19, 2012
+.Dt PMC.IVYBRIDGE 3
+.Os
+.Sh NAME
+.Nm pmc.ivybridge
+.Nd measurement events for
+.Tn Intel
+.Tn Ivy Bridge
+family CPUs
+.Sh LIBRARY
+.Lb libpmc
+.Sh SYNOPSIS
+.In pmc.h
+.Sh DESCRIPTION
+.Tn Intel
+.Tn "Ivy Bridge"
+CPUs contain PMCs conforming to version 2 of the
+.Tn Intel
+performance measurement architecture.
+These CPUs may contain up to three classes of PMCs:
+.Bl -tag -width "Li PMC_CLASS_IAP"
+.It Li PMC_CLASS_IAF
+Fixed-function counters that count only one hardware event per counter.
+.It Li PMC_CLASS_IAP
+Programmable counters that may be configured to count one of a defined
+set of hardware events.
+.El
+.Pp
+The number of PMCs available in each class and their widths need to be
+determined at run time by calling
+.Xr pmc_cpuinfo 3 .
+.Pp
+Intel Ivy Bridge PMCs are documented in
+.Rs
+.%B "Intel(R) 64 and IA-32 Architectures Software Developer's Manual"
+.%T "Volume 3B: System Programming Guide, Part 2"
+.%N "Order Number: 253669-043US"
+.%D May 2012
+.%Q "Intel Corporation"
+.Re
+.Ss IVYBRIDGE FIXED FUNCTION PMCS
+These PMCs and their supported events are documented in
+.Xr pmc.iaf 3 .
+.Ss IVYBRIDGE PROGRAMMABLE PMCS
+The programmable PMCs support the following capabilities:
+.Bl -column "PMC_CAP_INTERRUPT" "Support"
+.It Em Capability Ta Em Support
+.It PMC_CAP_CASCADE Ta \&No
+.It PMC_CAP_EDGE Ta Yes
+.It PMC_CAP_INTERRUPT Ta Yes
+.It PMC_CAP_INVERT Ta Yes
+.It PMC_CAP_READ Ta Yes
+.It PMC_CAP_PRECISE Ta \&No
+.It PMC_CAP_SYSTEM Ta Yes
+.It PMC_CAP_TAGGING Ta \&No
+.It PMC_CAP_THRESHOLD Ta Yes
+.It PMC_CAP_USER Ta Yes
+.It PMC_CAP_WRITE Ta Yes
+.El
+.Ss Event Qualifiers
+Event specifiers for these PMCs support the following common
+qualifiers:
+.Bl -tag -width indent
+.It Li rsp= Ns Ar value
+Configure the Off-core Response bits.
+.Bl -tag -width indent
+.It Li REQ_DMND_DATA_RD
+Counts the number of demand and DCU prefetch data reads of full and partial
+cachelines as well as demand data page table entry cacheline reads. Does not
+count L2 data read prefetches or instruction fetches.
+.It Li REQ_DMND_RFO
+Counts the number of demand and DCU prefetch reads for ownership (RFO)
+requests generated by a write to data cacheline. Does not count L2 RFO
+prefetches.
+.It Li REQ_DMND_IFETCH
+Counts the number of demand and DCU prefetch instruction cacheline reads.
+Does not count L2 code read prefetches.
+.It Li REQ_WB
+Counts the number of writeback (modified to exclusive) transactions.
+.It Li REQ_PF_DATA_RD
+Counts the number of data cacheline reads generated by L2 prefetchers.
+.It Li REQ_PF_RFO
+Counts the number of RFO requests generated by L2 prefetchers.
+.It Li REQ_PF_IFETCH
+Counts the number of code reads generated by L2 prefetchers.
+.It Li REQ_PF_LLC_DATA_RD
+L2 prefetcher to L3 for loads.
+.It Li REQ_PF_LLC_RFO
+RFO requests generated by L2 prefetcher
+.It Li REQ_PF_LLC_IFETCH
+L2 prefetcher to L3 for instruction fetches.
+.It Li REQ_BUS_LOCKS
+Bus lock and split lock requests.
+.It Li REQ_STRM_ST
+Streaming store requests.
+.It Li REQ_OTHER
+Any other request that crosses IDI, including I/O.
+.It Li RES_ANY
+Catch all value for any response types.
+.It Li RES_SUPPLIER_NO_SUPP
+No Supplier Information available.
+.It Li RES_SUPPLIER_LLC_HITM
+M-state initial lookup stat in L3.
+.It Li RES_SUPPLIER_LLC_HITE
+E-state.
+.It Li RES_SUPPLIER_LLC_HITS
+S-state.
+.It Li RES_SUPPLIER_LLC_HITF
+F-state.
+.It Li RES_SUPPLIER_LOCAL
+Local DRAM Controller.
+.It Li RES_SNOOP_SNP_NONE
+No details on snoop-related information.
+.It Li RES_SNOOP_SNP_NO_NEEDED
+No snoop was needed to satisfy the request.
+.It Li RES_SNOOP_SNP_MISS
+A snoop was needed and it missed all snooped caches:
+-For LLC Hit, ReslHitl was returned by all cores
+-For LLC Miss, Rspl was returned by all sockets and data was returned from
+DRAM.
+.It Li RES_SNOOP_HIT_NO_FWD
+A snoop was needed and it hits in at least one snooped cache. Hit denotes a
+cache-line was valid before snoop effect. This includes:
+-Snoop Hit w/ Invalidation (LLC Hit, RFO)
+-Snoop Hit, Left Shared (LLC Hit/Miss, IFetch/Data_RD)
+-Snoop Hit w/ Invalidation and No Forward (LLC Miss, RFO Hit S)
+In the LLC Miss case, data is returned from DRAM.
+.It Li RES_SNOOP_HIT_FWD
+A snoop was needed and data was forwarded from a remote socket.
+This includes:
+-Snoop Forward Clean, Left Shared (LLC Hit/Miss, IFetch/Data_RD/RFT).
+.It Li RES_SNOOP_HITM
+A snoop was needed and it HitM-ed in local or remote cache. HitM denotes a
+cache-line was in modified state before effect as a results of snoop. This
+includes:
+-Snoop HitM w/ WB (LLC miss, IFetch/Data_RD)
+-Snoop Forward Modified w/ Invalidation (LLC Hit/Miss, RFO)
+-Snoop MtoS (LLC Hit, IFetch/Data_RD).
+.It Li RES_NON_DRAM
+Target was non-DRAM system address. This includes MMIO transactions.
+.El
+.It Li cmask= Ns Ar value
+Configure the PMC to increment only if the number of configured
+events measured in a cycle is greater than or equal to
+.Ar value .
+.It Li edge
+Configure the PMC to count the number of de-asserted to asserted
+transitions of the conditions expressed by the other qualifiers.
+If specified, the counter will increment only once whenever a
+condition becomes true, irrespective of the number of clocks during
+which the condition remains true.
+.It Li inv
+Invert the sense of comparison when the
+.Dq Li cmask
+qualifier is present, making the counter increment when the number of
+events per cycle is less than the value specified by the
+.Dq Li cmask
+qualifier.
+.It Li os
+Configure the PMC to count events happening at processor privilege
+level 0.
+.It Li usr
+Configure the PMC to count events occurring at privilege levels 1, 2
+or 3.
+.El
+.Pp
+If neither of the
+.Dq Li os
+or
+.Dq Li usr
+qualifiers are specified, the default is to enable both.
+.Ss Event Specifiers (Programmable PMCs)
+Ivy Bridge programmable PMCs support the following events:
+.Bl -tag -width indent
+.It Li LD_BLOCKS.STORE_FORWARD
+.Pq Event 03H , Umask 02H
+loads blocked by overlapping with store buffer that cannot be forwarded .
+.It Li MISALIGN_MEM_REF.LOADS
+.Pq Event 05H , Umask 01H
+Speculative cache-line split load uops dispatched to L1D.
+.It Li MISALIGN_MEM_REF.STORES
+.Pq Event 05H , Umask 02H
+Speculative cache-line split Store- address uops dispatched to L1D.
+.It Li LD_BLOCKS_PARTIAL.ADDRESS_ALIAS
+.Pq Event 07H , Umask 01H
+False dependencies in MOB due to partial compare on address.
+.It Li DTLB_LOAD_MISSES.DEMAND_LD_MISS_CAUSES_A_WALK
+.Pq Event 08H , Umask 81H
+Misses in all TLB levels that cause a page walk of any page size from demand loads.
+.It Li DTLB_LOAD_MISSES.DEMAND_LD_WALK_COMPLETED
+.Pq Event 08H , Umask 82H
+Misses in all TLB levels that caused page walk completed of any size by demand loads.
+.It Li DTLB_LOAD_MISSES.DEMAND_LD_WALK_DURATION
+.Pq Event 08H , Umask 84H
+Cycle PMH is busy with a walk due to demand loads.
+.It Li UOPS_ISSUED.ANY
+.Pq Event 0EH , Umask 01H
+Increments each cycle the # of Uops issued by the RAT to RS.
+Set Cmask = 1, Inv = 1to count stalled cycles.
+Set Cmask = 1, Inv = 1, Any= 1to count stalled cycles of this core.
+.It Li UOPS_ISSUED.FLAGS_MERGE
+.Pq Event 0EH , Umask 10H
+Number of flags-merge uops allocated. Such uops adds delay.
+.It Li UOPS_ISSUED.SLOW_LEA
+.Pq Event 0EH , Umask 20H
+Number of slow LEA or similar uops allocated. Such uop has 3 sources (e.g. 2
+sources + immediate) regardless if as a result of LEA instruction or not.
+.It Li UOPS_ISSUED.SINGLE_MUL
+.Pq Event 0EH , Umask 40H
+Number of multiply packed/scalar single precision uops allocated.
+.It Li ARITH.FPU_DIV_ACTIVE
+.Pq Event 14H , Umask 01H
+Cycles that the divider is active, includes INT and FP. Set 'edge =1,
+cmask=1' to count the number of divides.
+.It Li L2_RQSTS.DEMAND_DATA_RD_HIT
+.Pq Event 24H , Umask 01H
+Demand Data Read requests that hit L2 cache.
+.It Li L2_RQSTS.ALL_DEMAND_DATA_RD
+.Pq Event 24H , Umask 03H
+Counts any demand and L1 HW prefetch data load requests to L2.
+.It Li L2_RQSTS.RFO_HITS
+.Pq Event 24H , Umask 04H
+Counts the number of store RFO requests that hit the L2 cache.
+.It Li L2_RQSTS.RFO_MISS
+.Pq Event 24H , Umask 08H
+Counts the number of store RFO requests that miss the L2 cache.
+.It Li L2_RQSTS.ALL_RFO
+.Pq Event 24H , Umask 0CH
+Counts all L2 store RFO requests.
+.It Li L2_RQSTS.CODE_RD_HIT
+.Pq Event 24H , Umask 10H
+Number of instruction fetches that hit the L2 cache.
+.It Li L2_RQSTS.CODE_RD_MISS
+.Pq Event 24H , Umask 20H
+Number of instruction fetches that missed the L2 cache.
+.It Li L2_RQSTS.ALL_CODE_RD
+.Pq Event 24H , Umask 30H
+Counts all L2 code requests.
+.It Li L2_RQSTS.PF_HIT
+.Pq Event 24H , Umask 40H
+Counts all L2 HW prefetcher requests that hit L2.
+.It Li L2_RQSTS.PF_MISS
+.Pq Event 24H , Umask 80H
+Counts all L2 HW prefetcher requests that missed L2.
+.It Li L2_RQSTS.ALL_PF
+.Pq Event 24H , Umask C0H
+Counts all L2 HW prefetcher requests.
+.It Li L2_STORE_LOCK_RQSTS.MISS
+.Pq Event 27H , Umask 01H
+RFOs that miss cache lines.
+.It Li L2_STORE_LOCK_RQSTS.HIT_M
+.Pq Event 27H , Umask 08H
+RFOs that hit cache lines in M state.
+.It Li L2_STORE_LOCK_RQSTS.ALL
+.Pq Event 27H , Umask 0FH
+RFOs that access cache lines in any state.
+.It Li L2_L1D_WB_RQSTS.MISS
+.Pq Event 28H , Umask 01H
+Not rejected writebacks that missed LLC.
+.It Li L2_L1D_WB_RQSTS.HIT_E
+.Pq Event 28H , Umask 04H
+Not rejected writebacks from L1D to L2 cache lines in E state.
+.It Li L2_L1D_WB_RQSTS.HIT_M
+.Pq Event 28H , Umask 08H
+Not rejected writebacks from L1D to L2 cache lines in M state.
+.It Li L2_L1D_WB_RQSTS.ALL
+.Pq Event 28H , Umask 0FH
+Not rejected writebacks from L1D to L2 cache lines in any state.
+.It Li LONGEST_LAT_CACHE.REFERENCE
+.Pq Event 2EH , Umask 4FH
+This event counts requests originating from the core that reference a cache
+line in the last level cache.
+.It Li LONGEST_LAT_CACHE.MISS
+.Pq Event 2EH , Umask 41H
+This event counts each cache miss condition for references to the last level
+cache.
+.It Li CPU_CLK_UNHALTED.THREAD_P
+.Pq Event 3CH , Umask 00H
+Counts the number of thread cycles while the thread is not in a halt state.
+The thread enters the halt state when it is running the HLT instruction. The
+core frequency may change from time to time due to power or thermal
+throttling.
+.It Li CPU_CLK_THREAD_UNHALTED.REF_XCLK
+.Pq Event 3CH , Umask 01H
+Increments at the frequency of XCLK (100 MHz) when not halted.
+.It Li L1D_PEND_MISS.PENDING
+.Pq Event 48H , Umask 01H
+Increments the number of outstanding L1D misses every cycle. Set Cmaks = 1
+and Edge =1 to count occurrences.
+Counter 2 only.
+Set Cmask = 1 to count cycles.
+.It Li DTLB_STORE_MISSES.MISS_CAUSES_A_WALK
+.Pq Event 49H , Umask 01H
+Miss in all TLB levels causes an page walk of any page size (4K/2M/4M/1G).
+.It Li DTLB_STORE_MISSES.WALK_COMPLETED
+.Pq Event 49H , Umask 02H
+Miss in all TLB levels causes a page walk that completes of any page size
+(4K/2M/4M/1G).
+.It Li DTLB_STORE_MISSES.WALK_DURATION
+.Pq Event 49H , Umask 04H
+Cycles PMH is busy with this walk.
+.It Li DTLB_STORE_MISSES.STLB_HIT
+.Pq Event 49H , Umask 10H
+Store operations that miss the first TLB level but hit the second and do not
+cause page walks.
+.It Li LOAD_HIT_PRE.SW_PF
+.Pq Event 4CH , Umask 01H
+Non-SW-prefetch load dispatches that hit fill buffer allocated for S/W prefetch.
+.It Li LOAD_HIT_PRE.HW_PF
+.Pq Event 4CH , Umask 02H
+Non-SW-prefetch load dispatches that hit fill buffer allocated for H/W prefetch.
+.It Li L1D.REPLACEMENT
+.Pq Event 51H , Umask 01H
+Counts the number of lines brought into the L1 data cache.
+.It Li MOVE_ELIMINATION.INT_NOT_ELIMINATED
+.Pq Event 58H , Umask 01H
+Number of integer Move Elimination candidate uops that were not eliminated.
+.It Li MOVE_ELIMINATION.SIMD_NOT_ELIMINATED
+.Pq Event 58H , Umask 02H
+Number of SIMD Move Elimination candidate uops that were not eliminated.
+.It Li MOVE_ELIMINATION.INT_ELIMINATED
+.Pq Event 58H , Umask 04H
+Number of integer Move Elimination candidate uops that were eliminated.
+.It Li MOVE_ELIMINATION.SIMD_ELIMINATED
+.Pq Event 58H , Umask 08H
+Number of SIMD Move Elimination candidate uops that were eliminated.
+.It Li CPL_CYCLES.RING0
+.Pq Event 5CH , Umask 01H
+Unhalted core cycles when the thread is in ring 0.
+Use Edge to count transition.
+.It Li CPL_CYCLES.RING123
+.Pq Event 5CH , Umask 02H
+Unhalted core cycles when the thread is not in ring 0.
+.It Li RS_EVENTS.EMPTY_CYCLES
+.Pq Event 5EH , Umask 01H
+Cycles the RS is empty for the thread.
+.It Li TLB_ACCESS.LOAD_STLB_HIT
+.Pq Event 5FH , Umask 01H
+Counts load operations that missed 1st level DTLB but hit the 2nd level.
+.It Li OFFCORE_REQUESTS_OUTSTANDING.DEMAND_DATA_RD
+.Pq Event 60H , Umask 01H
+Offcore outstanding Demand Data Read transactions in SQ to uncore. Set
+Cmask=1 to count cycles.
+.It Li OFFCORE_REQUESTS_OUTSTANDING.DEMAND_CODE_RD
+.Pq Event 60H , Umask 02H
+Offcore outstanding Demand Code Read transactions in SQ to uncore. Set
+Cmask=1 to count cycles.
+.It Li OFFCORE_REQUESTS_OUTSTANDING.DEMAND_RFO
+.Pq Event 60H , Umask 04H
+Offcore outstanding RFO store transactions in SQ to uncore. Set Cmask=1 to
+count cycles.
+.It Li OFFCORE_REQUESTS_OUTSTANDING.ALL_DATA_RD
+.Pq Event 60H , Umask 08H
+Offcore outstanding cacheable data read transactions in SQ to uncore. Set
+Cmask=1 to count cycles.
+.It Li LOCK_CYCLES.SPLIT_LOCK_UC_LOCK_DURATION
+.Pq Event 63H , Umask 01H
+Cycles in which the L1D and L2 are locked, due to a UC lock or split lock.
+.It Li LOCK_CYCLES.CACHE_LOCK_DURATION
+.Pq Event 63H , Umask 02H
+Cycles in which the L1D is locked.
+.It Li IDQ.EMPTY
+.Pq Event 79H , Umask 02H
+Counts cycles the IDQ is empty.
+.It Li IDQ.MITE_UOPS
+.Pq Event 79H , Umask 04H
+Increment each cycle # of uops delivered to IDQ from MITE path.
+Can combine Umask 04H and 20H.
+Set Cmask = 1 to count cycles.
+.It Li IDQ.DSB_UOPS
+.Pq Event 79H , Umask 08H
+Increment each cycle. # of uops delivered to IDQ from DSB path.
+Can combine Umask 08H and 10H
+Set Cmask = 1 to count cycles.
+.It Li IDQ.MS_DSB_UOPS
+.Pq Event 79H , Umask 10H
+Increment each cycle # of uops delivered to IDQ when MS_busy by DSB. Set
+Cmask = 1 to count cycles. Add Edge=1 to count # of delivery.
+Can combine Umask 04H, 08H.
+.It Li IDQ.MS_MITE_UOPS
+.Pq Event 79H , Umask 20H
+Increment each cycle # of uops delivered to IDQ when MS_busy by MITE. Set
+Cmask = 1 to count cycles.
+Can combine Umask 04H, 08H.
+.It Li IDQ.MS_UOPS
+.Pq Event 79H , Umask 30H
+Increment each cycle # of uops delivered to IDQ from MS by either DSB or
+MITE. Set Cmask = 1 to count cycles.
+Can combine Umask 04H, 08H.
+.It Li IDQ.ALL_DSB_CYCLES_ANY_UOPS
+.Pq Event 79H , Umask 18H
+Counts cycles DSB is delivered at least one uops. Set Cmask = 1.
+.It Li IDQ.ALL_DSB_CYCLES_4_UOPS
+.Pq Event 79H , Umask 18H
+Counts cycles DSB is delivered four uops. Set Cmask = 4.
+.It Li IDQ.ALL_MITE_CYCLES_ANY_UOPS
+.Pq Event 79H , Umask 24H
+Counts cycles MITE is delivered at least one uops. Set Cmask = 1.
+.It Li IDQ.ALL_MITE_CYCLES_4_UOPS
+.Pq Event 79H , Umask 24H
+Counts cycles MITE is delivered four uops. Set Cmask = 4.
+.It Li IDQ.MITE_ALL_UOPS
+.Pq Event 79H , Umask 3CH
+# of uops delivered to IDQ from any path.
+.It Li ICACHE.MISSES
+.Pq Event 80H , Umask 02H
+Number of Instruction Cache, Streaming Buffer and Victim Cache Misses.
+Includes UC accesses.
+.It Li ITLB_MISSES.MISS_CAUSES_A_WALK
+.Pq Event 85H , Umask 01H
+Misses in all ITLB levels that cause page walks.
+.It Li ITLB_MISSES.WALK_COMPLETED
+.Pq Event 85H , Umask 02H
+Misses in all ITLB levels that cause completed page walks.
+.It Li ITLB_MISSES.WALK_DURATION
+.Pq Event 85H , Umask 04H
+Cycle PMH is busy with a walk.
+.It Li ITLB_MISSES.STLB_HIT
+.Pq Event 85H , Umask 10H
+Number of cache load STLB hits. No page walk.
+.It Li ILD_STALL.LCP
+.Pq Event 87H , Umask 01H
+Stalls caused by changing prefix length of the instruction.
+.It Li ILD_STALL.IQ_FULL
+.Pq Event 87H , Umask 04H
+Stall cycles due to IQ is full.
+.It Li BR_INST_EXEC.COND
+.Pq Event 88H , Umask 01H
+Qualify conditional near branch instructions executed, but not necessarily
+retired.
+Must combine with umask 40H, 80H.
+.It Li BR_INST_EXEC.DIRECT_JMP
+.Pq Event 88H , Umask 02H
+Qualify all unconditional near branch instructions excluding calls and
+indirect branches.
+Must combine with umask 80H.
+.It Li BR_INST_EXEC.INDIRECT_JMP_NON_CALL_RET
+.Pq Event 88H , Umask 04H
+Qualify executed indirect near branch instructions that are not calls nor
+returns.
+Must combine with umask 80H.
+.It Li BR_INST_EXEC.RETURN_NEAR
+.Pq Event 88H , Umask 08H
+Qualify indirect near branches that have a return mnemonic.
+Must combine with umask 80H.
+.It Li BR_INST_EXEC.DIRECT_NEAR_CALL
+.Pq Event 88H , Umask 10H
+Qualify unconditional near call branch instructions, excluding non call
+branch, executed.
+Must combine with umask 80H.
+.It Li BR_INST_EXEC.INDIRECT_NEAR_CALL
+.Pq Event 88H , Umask 20H
+Qualify indirect near calls, including both register and memory indirect,
+executed.
+Must combine with umask 80H.
+.It Li BR_INST_EXEC.NONTAKEN
+.Pq Event 88H , Umask 40H
+Qualify non-taken near branches executed.
+Applicable to umask 01H only.
+.It Li BR_INST_EXEC.TAKEN
+.Pq Event 88H , Umask 80H
+Qualify taken near branches executed. Must combine with 01H,02H, 04H, 08H,
+10H, 20H.
+.It Li BR_INST_EXEC.ALL_BRANCHES
+.Pq Event 88H , Umask FFH
+Counts all near executed branches (not necessarily retired).
+.It Li BR_MISP_EXEC.COND
+.Pq Event 89H , Umask 01H
+Qualify conditional near branch instructions mispredicted.
+Must combine with umask 40H, 80H.
+.It Li BR_MISP_EXEC.INDIRECT_JMP_NON_CALL_RET
+.Pq Event 89H , Umask 04H
+Qualify mispredicted indirect near branch instructions that are not calls
+nor returns.
+Must combine with umask 80H.
+.It Li BR_MISP_EXEC.RETURN_NEAR
+.Pq Event 89H , Umask 08H
+Qualify mispredicted indirect near branches that have a return mnemonic.
+Must combine with umask 80H.
+.It Li BR_MISP_EXEC.DIRECT_NEAR_CALL
+.Pq Event 89H , Umask 10H
+Qualify mispredicted unconditional near call branch instructions, excluding
+non call branch, executed.
+Must combine with umask 80H.
+.It Li BR_MISP_EXEC.INDIRECT_NEAR_CALL
+.Pq Event 89H , Umask 20H
+Qualify mispredicted indirect near calls, including both register and memory
+indirect, executed.
+Must combine with umask 80H.
+.It Li BR_MISP_EXEC.NONTAKEN
+.Pq Event 89H , Umask 40H
+Qualify mispredicted non-taken near branches executed.
+Applicable to umask 01H only.
+.It Li BR_MISP_EXEC.TAKEN
+.Pq Event 89H , Umask 80H
+Qualify mispredicted taken near branches executed. Must combine with
+01H,02H, 04H, 08H, 10H, 20H.
+.It Li BR_MISP_EXEC.ALL_BRANCHES
+.Pq Event 89H , Umask FFH
+Counts all near executed branches (not necessarily retired).
+.It Li IDQ_UOPS_NOT_DELIVERED.CORE
+.Pq Event 9CH , Umask 01H
+Count number of non-delivered uops to RAT per thread.
+Use Cmask to qualify uop b/w.
+.It Li UOPS_DISPATCHED_PORT.PORT_0
+.Pq Event A1H , Umask 01H
+Cycles which a Uop is dispatched on port 0.
+.It Li UOPS_DISPATCHED_PORT.PORT_1
+.Pq Event A1H , Umask 02H
+Cycles which a Uop is dispatched on port 1.
+.It Li UOPS_DISPATCHED_PORT.PORT_2_LD
+.Pq Event A1H , Umask 04H
+Cycles which a load uop is dispatched on port 2.
+.It Li UOPS_DISPATCHED_PORT.PORT_2_STA
+.Pq Event A1H , Umask 08H
+Cycles which a store address uop is dispatched on port 2.
+.It Li UOPS_DISPATCHED_PORT.PORT_2
+.Pq Event A1H , Umask 0CH
+Cycles which a Uop is dispatched on port 2.
+.It Li UOPS_DISPATCHED_PORT.PORT_3_LD
+.Pq Event A1H , Umask 10H
+Cycles which a load uop is dispatched on port 3.
+.It Li UOPS_DISPATCHED_PORT.PORT_3_STA
+.Pq Event A1H , Umask 20H
+Cycles which a store address uop is dispatched on port 3.
+.It Li UOPS_DISPATCHED_PORT.PORT_3
+.Pq Event A1H , Umask 30H
+Cycles which a Uop is dispatched on port 3.
+.It Li UOPS_DISPATCHED_PORT.PORT_4
+.Pq Event A1H , Umask 40H
+Cycles which a Uop is dispatched on port 4.
+.It Li UOPS_DISPATCHED_PORT.PORT_5
+.Pq Event A1H , Umask 80H
+Cycles which a Uop is dispatched on port 5.
+.It Li RESOURCE_STALLS.ANY
+.Pq Event A2H , Umask 01H
+Cycles Allocation is stalled due to Resource Related reason.
+.It Li RESOURCE_STALLS.RS
+.Pq Event A2H , Umask 04H
+Cycles stalled due to no eligible RS entry available.
+.It Li RESOURCE_STALLS.SB
+.Pq Event A2H , Umask 08H
+Cycles stalled due to no store buffers available. (not including draining
+form sync).
+.It Li RESOURCE_STALLS.ROB
+.Pq Event A2H , Umask 10H
+Cycles stalled due to re-order buffer full.
+.It Li DSB2MITE_SWITCHES.COUNT
+.Pq Event ABH , Umask 01H
+Number of DSB to MITE switches.
+.It Li DSB2MITE_SWITCHES.PENALTY_CYCLES
+.Pq Event ABH , Umask 02H
+Cycles DSB to MITE switches caused delay.
+.It Li DSB_FILL.EXCEED_DSB_LINES
+.Pq Event ACH , Umask 08H
+DSB Fill encountered > 3 DSB lines.
+.It Li ITLB.ITLB_FLUSH
+.Pq Event AEH , Umask 01H
+Counts the number of ITLB flushes, includes 4k/2M/4M pages.
+.It Li OFFCORE_REQUESTS.DEMAND_DATA_RD
+.Pq Event B0H , Umask 01H
+Demand data read requests sent to uncore.
+.It Li OFFCORE_REQUESTS.DEMAND_CODE_RD
+.Pq Event B0H , Umask 02H
+Demand code read requests sent to uncore.
+.It Li OFFCORE_REQUESTS.DEMAND_RFO
+.Pq Event B0H , Umask 04H
+Demand RFO read requests sent to uncore, including regular RFOs, locks,
+ItoM.
+.It Li OFFCORE_REQUESTS.ALL_DATA_RD
+.Pq Event B0H , Umask 08H
+Data read requests sent to uncore (demand and prefetch).
+.It Li UOPS_EXECUTED.THREAD
+.Pq Event B1H , Umask 01H
+Counts total number of uops to be executed per-thread each cycle. Set Cmask
+= 1, INV =1 to count stall cycles.
+.It Li UOPS_EXECUTED.CORE
+.Pq Event B1H , Umask 02H
+Counts total number of uops to be executed per-core each cycle.
+Do not need to set ANY.
+.It Li OFF_CORE_RESPONSE_0
+.Pq Event B7H , Umask 01H
+Off-core Response Performance Monitoring.
+PMC0 only.
+Requires programming MSR 01A6H.
+.It Li OFF_CORE_RESPONSE_1
+.Pq Event BBH , Umask 01H
+Off-core Response Performance Monitoring.
+PMC3 only.
+Requires programming MSR 01A7H.
+.It Li TLB_FLUSH.DTLB_THREAD
+.Pq Event BDH , Umask 01H
+DTLB flush attempts of the thread- specific entries.
+.It Li TLB_FLUSH.STLB_ANY
+.Pq Event BDH , Umask 20H
+Count number of STLB flush attempts.
+.It Li INST_RETIRED.ANY_P
+.Pq Event C0H , Umask 00H
+Number of instructions at retirement.
+.It Li INST_RETIRED.ALL
+.Pq Event C0H , Umask 01H
+Precise instruction retired event with HW to reduce effect of PEBS shadow in
+IP distribution.
+PMC1 only.
+Must quiesce other PMCs.
+.It Li OTHER_ASSISTS.AVX_STORE
+.Pq Event C1H , Umask 08H
+Number of assists associated with 256-bit AVX store operations.
+.It Li OTHER_ASSISTS.AVX_TO_SSE
+.Pq Event C1H , Umask 10H
+Number of transitions from AVX- 256 to legacy SSE when penalty applicable.
+.It Li OTHER_ASSISTS.SSE_TO_AVX
+.Pq Event C1H , Umask 20H
+Number of transitions from SSE to AVX-256 when penalty applicable.
+.It Li UOPS_RETIRED.ALL
+.Pq Event C2H , Umask 01H
+Counts the number of micro-ops retired, Use cmask=1 and invert to count
+active cycles or stalled cycles.
+Supports PEBS, use Any=1 for core granular.
+.It Li UOPS_RETIRED.RETIRE_SLOTS
+.Pq Event C2H , Umask 02H
+Counts the number of retirement slots used each cycle.
+.It Li MACHINE_CLEARS.MEMORY_ORDERING
+.Pq Event C3H , Umask 02H
+Counts the number of machine clears due to memory order conflicts.
+.It Li MACHINE_CLEARS.SMC
+.Pq Event C3H , Umask 04H
+Number of self-modifying-code machine clears detected.
+.It Li MACHINE_CLEARS.MASKMOV
+.Pq Event C3H , Umask 20H
+Counts the number of executed AVX masked load operations that refer to an
+illegal address range with the mask bits set to 0.
+.It Li BR_INST_RETIRED.ALL_BRANCHES
+.Pq Event C4H , Umask 00H
+Branch instructions at retirement.
+.It Li BR_INST_RETIRED.CONDITIONAL
+.Pq Event C4H , Umask 01H
+Counts the number of conditional branch instructions retired.
+Supports PEBS.
+.It Li BR_INST_RETIRED.NEAR_CALL
+.Pq Event C4H , Umask 02H
+Direct and indirect near call instructions retired.
+.It Li BR_INST_RETIRED.ALL_BRANCHES
+.Pq Event C4H , Umask 04H
+Counts the number of branch instructions retired.
+.It Li BR_INST_RETIRED.NEAR_RETURN
+.Pq Event C4H , Umask 08H
+Counts the number of near return instructions retired.
+.It Li BR_INST_RETIRED.NOT_TAKEN
+.Pq Event C4H , Umask 10H
+Counts the number of not taken branch instructions retired.
+.It Li BR_INST_RETIRED.NEAR_TAKEN
+.Pq Event C4H , Umask 20H
+Number of near taken branches retired.
+.It Li BR_INST_RETIRED.FAR_BRANCH
+.Pq Event C4H , Umask 40H
+Number of far branches retired.
+.It Li BR_MISP_RETIRED.ALL_BRANCHES
+.Pq Event C5H , Umask 00H
+Mispredicted branch instructions at retirement.
+.It Li BR_MISP_RETIRED.CONDITIONAL
+.Pq Event C5H , Umask 01H
+Mispredicted conditional branch instructions retired.
+Supports PEBS.
+.It Li BR_MISP_RETIRED.NEAR_CALL
+.Pq Event C5H , Umask 02H
+Direct and indirect mispredicted near call instructions retired.
+.It Li BR_MISP_RETIRED.ALL_BRANCHES
+.Pq Event C5H , Umask 04H
+Mispredicted macro branch instructions retired.
+.It Li BR_MISP_RETIRED.NOT_TAKEN
+.Pq Event C5H , Umask 10H
+Mispredicted not taken branch instructions retired.
+.It Li BR_MISP_RETIRED.TAKEN
+.Pq Event C5H , Umask 20H
+Mispredicted taken branch instructions retired.
+.It Li FP_ASSIST.X87_OUTPUT
+.Pq Event CAH , Umask 02H
+Number of X87 FP assists due to Output values.
+.It Li FP_ASSIST.X87_INPUT
+.Pq Event CAH , Umask 04H
+Number of X87 FP assists due to input values.
+.It Li FP_ASSIST.SIMD_OUTPUT
+.Pq Event CAH , Umask 08H
+Number of SIMD FP assists due to Output values.
+.It Li FP_ASSIST.SIMD_INPUT
+.Pq Event CAH , Umask 10H
+Number of SIMD FP assists due to input values.
+.It Li FP_ASSIST.ANY
+.Pq Event CAH , Umask 1EH
+Cycles with any input/output SSE* or FP assists.
+.It Li ROB_MISC_EVENTS.LBR_INSERTS
+.Pq Event CCH , Umask 20H
+Count cases of saving new LBR records by hardware.
+.It Li MEM_TRANS_RETIRED.LOAD_LATENCY
+.Pq Event CDH , Umask 01H
+Sample loads with specified latency threshold.
+PMC3 only.
+Specify threshold in MSR 0x3F6.
+.It Li MEM_TRANS_RETIRED.PRECISE_STORE
+.Pq Event CDH , Umask 02H
+Sample stores and collect precise store operation via PEBS record.
+PMC3 only.
+.It Li MEM_UOP_RETIRED.LOADS
+.Pq Event D0H , Umask 01H
+Qualify retired memory uops that are loads. Combine with umask 10H, 20H,
+40H, 80H.
+Supports PEBS.
+.It Li MEM_UOP_RETIRED.STORES
+.Pq Event D0H , Umask 02H
+Qualify retired memory uops that are stores. Combine with umask 10H, 20H,
+40H, 80H.
+.It Li MEM_UOP_RETIRED.STLB_MISS
+.Pq Event D0H , Umask 10H
+Qualify retired memory uops with STLB miss. Must combine with umask 01H,
+02H, to produce counts.
+.It Li MEM_UOP_RETIRED.LOCK
+.Pq Event D0H , Umask 20H
+Qualify retired memory uops with lock. Must combine with umask 01H, 02H, to
+produce counts.
+.It Li MEM_UOP_RETIRED.SPLIT
+.Pq Event D0H , Umask 40H
+Qualify retired memory uops with line split. Must combine with umask 01H,
+02H, to produce counts.
+.It Li MEM_UOP_RETIRED.ALL
+.Pq Event D0H , Umask 80H
+Qualify any retired memory uops. Must combine with umask 01H, 02H, to
+produce counts.
+.It Li MEM_LOAD_UOPS_RETIRED.L1_HIT
+.Pq Event D1H , Umask 01H
+Retired load uops with L1 cache hits as data sources.
+Supports PEBS.
+.It Li MEM_LOAD_UOPS_RETIRED.L2_HIT
+.Pq Event D1H , Umask 02H
+Retired load uops with L2 cache hits as data sources.
+.It Li MEM_LOAD_UOPS_RETIRED.LLC_HIT
+.Pq Event D1H , Umask 04H
+Retired load uops with LLC cache hits as data sources.
+.It Li MEM_LOAD_UOPS_RETIRED.HIT_LFB
+.Pq Event D1H , Umask 40H
+Retired load uops which data sources were load uops missed L1 but hit FB due
+to preceding miss to the same cache line with data not ready.
+.It Li MEM_LOAD_UOPS_LLC_HIT_RETIRED.XSNP_MISS
+.Pq Event D2H , Umask 01H
+Retired load uops which data sources were LLC hit and cross-core snoop
+missed in on-pkg core cache.
+Supports PEBS.
+.It Li MEM_LOAD_UOPS_LLC_HIT_RETIRED.XSNP_HIT
+.Pq Event D2H , Umask 02H
+Retired load uops which data sources were LLC and cross-core snoop hits in
+on-pkg core cache.
+Supports PEBS.
+.It Li MEM_LOAD_UOPS_LLC_HIT_RETIRED.XSNP_HITM
+.Pq Event D2H , Umask 04H
+Retired load uops which data sources were HitM responses from shared LLC.
+.It Li MEM_LOAD_UOPS_LLC_HIT_RETIRED.XSNP_NONE
+.Pq Event D2H , Umask 08H
+Retired load uops which data sources were hits in LLC without snoops
+required.
+.It Li MEM_LOAD_UOPS_LLC_MISS_RETIRED.LOCAL_DRAM
+.Pq Event D3H , Umask 01H
+Retired load uops which data sources missed LLC but serviced from local
+dram.
+Supports PEBS.
+.It Li L2_TRANS.DEMAND_DATA_RD
+.Pq Event F0H , Umask 01H
+Demand Data Read requests that access L2 cache.
+.It Li L2_TRANS.RFO
+.Pq Event F0H , Umask 02H
+RFO requests that access L2 cache.
+.It Li L2_TRANS.CODE_RD
+.Pq Event F0H , Umask 04H
+L2 cache accesses when fetching instructions.
+.It Li L2_TRANS.ALL_PF
+.Pq Event F0H , Umask 08H
+Any MLC or LLC HW prefetch accessing L2, including rejects.
+.It Li L2_TRANS.L1D_WB
+.Pq Event F0H , Umask 10H
+L1D writebacks that access L2 cache.
+.It Li L2_TRANS.L2_FILL
+.Pq Event F0H , Umask 20H
+L2 fill requests that access L2 cache.
+.It Li L2_TRANS.L2_WB
+.Pq Event F0H , Umask 40H
+L2 writebacks that access L2 cache.
+.It Li L2_TRANS.ALL_REQUESTS
+.Pq Event F0H , Umask 80H
+Transactions accessing L2 pipe.
+.It Li L2_LINES_IN.I
+.Pq Event F1H , Umask 01H
+L2 cache lines in I state filling L2.
+Counting does not cover rejects.
+.It Li L2_LINES_IN.S
+.Pq Event F1H , Umask 02H
+L2 cache lines in S state filling L2.
+Counting does not cover rejects.
+.It Li L2_LINES_IN.E
+.Pq Event F1H , Umask 04H
+L2 cache lines in E state filling L2.
+Counting does not cover rejects.
+.It Li L2_LINES_IN.ALL
+.Pq Event F1H , Umask 07H
+L2 cache lines filling L2.
+Counting does not cover rejects.
+.It Li L2_LINES_OUT.DEMAND_CLEAN
+.Pq Event F2H , Umask 01H
+Clean L2 cache lines evicted by demand.
+.It Li L2_LINES_OUT.DEMAND_DIRTY
+.Pq Event F2H , Umask 02H
+Dirty L2 cache lines evicted by demand.
+.It Li L2_LINES_OUT.PF_CLEAN
+.Pq Event F2H , Umask 04H
+Clean L2 cache lines evicted by the MLC prefetcher.
+.It Li L2_LINES_OUT.PF_DIRTY
+.Pq Event F2H , Umask 08H
+Dirty L2 cache lines evicted by the MLC prefetcher.
+.El
+.Sh SEE ALSO
+.Xr pmc 3 ,
+.Xr pmc.atom 3 ,
+.Xr pmc.core 3 ,
+.Xr pmc.iaf 3 ,
+.Xr pmc.ucf 3 ,
+.Xr pmc.k7 3 ,
+.Xr pmc.k8 3 ,
+.Xr pmc.p4 3 ,
+.Xr pmc.p5 3 ,
+.Xr pmc.p6 3 ,
+.Xr pmc.corei7 3 ,
+.Xr pmc.corei7uc 3 ,
+.Xr pmc.sandybridge 3 ,
+.Xr pmc.sandybridgeuc 3 ,
+.Xr pmc.sandybridgexeon 3 ,
+.Xr pmc.westmere 3 ,
+.Xr pmc.westmereuc 3 ,
+.Xr pmc.soft 3 ,
+.Xr pmc.tsc 3 ,
+.Xr pmc_cpuinfo 3 ,
+.Xr pmclog 3 ,
+.Xr hwpmc 4
+.Sh HISTORY
+The
+.Nm pmc
+library first appeared in
+.Fx 6.0 .
+.Sh AUTHORS
+The
+.Lb libpmc
+library was written by
+.An "Joseph Koshy"
+.Aq jkoshy@FreeBSD.org .
+The support for the Ivy Bridge
+microarchitecture was written by
+.An "Fabien Thomas"
+.Aq fabient@FreeBSD.org .
diff --git a/lib/libpmc/pmc.sandybridge.3 b/lib/libpmc/pmc.sandybridge.3
index e0c7eb9..62f8f28 100644
--- a/lib/libpmc/pmc.sandybridge.3
+++ b/lib/libpmc/pmc.sandybridge.3
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd February 12, 2012
+.Dd October 19, 2012
.Dt PMC.SANDYBRIDGE 3
.Os
.Sh NAME
@@ -93,55 +93,80 @@ qualifiers:
.It Li rsp= Ns Ar value
Configure the Off-core Response bits.
.Bl -tag -width indent
-.It Li DMND_DATA_RD
-Counts the number of demand and DCU prefetch data reads of full
-and partial cachelines as well as demand data page table entry
-cacheline reads.
-Does not count L2 data read prefetches or instruction fetches.
-.It Li DMND_RFO
-Counts the number of demand and DCU prefetch reads for ownership
-(RFO) requests generated by a write to data cacheline.
-Does not count L2 RFO.
-.It Li DMND_IFETCH
-Counts the number of demand and DCU prefetch instruction cacheline
-reads.
+.It Li REQ_DMND_DATA_RD
+Counts the number of demand and DCU prefetch data reads of full and partial
+cachelines as well as demand data page table entry cacheline reads. Does not
+count L2 data read prefetches or instruction fetches.
+.It Li REQ_DMND_RFO
+Counts the number of demand and DCU prefetch reads for ownership (RFO)
+requests generated by a write to data cacheline. Does not count L2 RFO
+prefetches.
+.It Li REQ_DMND_IFETCH
+Counts the number of demand and DCU prefetch instruction cacheline reads.
Does not count L2 code read prefetches.
-.It Li WB
+.It Li REQ_WB
Counts the number of writeback (modified to exclusive) transactions.
-.It Li PF_DATA_RD
+.It Li REQ_PF_DATA_RD
Counts the number of data cacheline reads generated by L2 prefetchers.
-.It Li PF_RFO
+.It Li REQ_PF_RFO
Counts the number of RFO requests generated by L2 prefetchers.
-.It Li PF_IFETCH
+.It Li REQ_PF_IFETCH
Counts the number of code reads generated by L2 prefetchers.
-.It Li OTHER
-Counts one of the following transaction types, including L3 invalidate,
-I/O, full or partial writes, WC or non-temporal stores, CLFLUSH, Fences,
-lock, unlock, split lock.
-.It Li UNCORE_HIT
-L3 Hit: local or remote home requests that hit L3 cache in the uncore
-with no coherency actions required (snooping).
-.It Li OTHER_CORE_HIT_SNP
-L3 Hit: local or remote home requests that hit L3 cache in the uncore
-and was serviced by another core with a cross core snoop where no modified
-copies were found (clean).
-.It Li OTHER_CORE_HITM
-L3 Hit: local or remote home requests that hit L3 cache in the uncore
-and was serviced by another core with a cross core snoop where modified
-copies were found (HITM).
-.It Li REMOTE_CACHE_FWD
-L3 Miss: local homed requests that missed the L3 cache and was serviced
-by forwarded data following a cross package snoop where no modified
-copies found.
-(Remote home requests are not counted)
-.It Li REMOTE_DRAM
-L3 Miss: remote home requests that missed the L3 cache and were serviced
-by remote DRAM.
-.It Li LOCAL_DRAM
-L3 Miss: local home requests that missed the L3 cache and were serviced
-by local DRAM.
-.It Li NON_DRAM
-Non-DRAM requests that were serviced by IOH.
+.It Li REQ_PF_LLC_DATA_RD
+L2 prefetcher to L3 for loads.
+.It Li REQ_PF_LLC_RFO
+RFO requests generated by L2 prefetcher
+.It Li REQ_PF_LLC_IFETCH
+L2 prefetcher to L3 for instruction fetches.
+.It Li REQ_BUS_LOCKS
+Bus lock and split lock requests.
+.It Li REQ_STRM_ST
+Streaming store requests.
+.It Li REQ_OTHER
+Any other request that crosses IDI, including I/O.
+.It Li RES_ANY
+Catch all value for any response types.
+.It Li RES_SUPPLIER_NO_SUPP
+No Supplier Information available.
+.It Li RES_SUPPLIER_LLC_HITM
+M-state initial lookup stat in L3.
+.It Li RES_SUPPLIER_LLC_HITE
+E-state.
+.It Li RES_SUPPLIER_LLC_HITS
+S-state.
+.It Li RES_SUPPLIER_LLC_HITF
+F-state.
+.It Li RES_SUPPLIER_LOCAL
+Local DRAM Controller.
+.It Li RES_SNOOP_SNP_NONE
+No details on snoop-related information.
+.It Li RES_SNOOP_SNP_NO_NEEDED
+No snoop was needed to satisfy the request.
+.It Li RES_SNOOP_SNP_MISS
+A snoop was needed and it missed all snooped caches:
+-For LLC Hit, ReslHitl was returned by all cores
+-For LLC Miss, Rspl was returned by all sockets and data was returned from
+DRAM.
+.It Li RES_SNOOP_HIT_NO_FWD
+A snoop was needed and it hits in at least one snooped cache. Hit denotes a
+cache-line was valid before snoop effect. This includes:
+-Snoop Hit w/ Invalidation (LLC Hit, RFO)
+-Snoop Hit, Left Shared (LLC Hit/Miss, IFetch/Data_RD)
+-Snoop Hit w/ Invalidation and No Forward (LLC Miss, RFO Hit S)
+In the LLC Miss case, data is returned from DRAM.
+.It Li RES_SNOOP_HIT_FWD
+A snoop was needed and data was forwarded from a remote socket.
+This includes:
+-Snoop Forward Clean, Left Shared (LLC Hit/Miss, IFetch/Data_RD/RFT).
+.It Li RES_SNOOP_HITM
+A snoop was needed and it HitM-ed in local or remote cache. HitM denotes a
+cache-line was in modified state before effect as a results of snoop. This
+includes:
+-Snoop HitM w/ WB (LLC miss, IFetch/Data_RD)
+-Snoop Forward Modified w/ Invalidation (LLC Hit/Miss, RFO)
+-Snoop MtoS (LLC Hit, IFetch/Data_RD).
+.It Li RES_NON_DRAM
+Target was non-DRAM system address. This includes MMIO transactions.
.El
.It Li cmask= Ns Ar value
Configure the PMC to increment only if the number of configured
@@ -907,6 +932,7 @@ Split locks in SQ.
.Xr pmc.p5 3 ,
.Xr pmc.p6 3 ,
.Xr pmc.sandybridgeuc 3 ,
+.Xr pmc.sandybridgexeon 3 ,
.Xr pmc.soft 3 ,
.Xr pmc.tsc 3 ,
.Xr pmc.ucf 3 ,
diff --git a/lib/libpmc/pmc.sandybridgeuc.3 b/lib/libpmc/pmc.sandybridgeuc.3
index 2078482..f952533 100644
--- a/lib/libpmc/pmc.sandybridgeuc.3
+++ b/lib/libpmc/pmc.sandybridgeuc.3
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd February 12, 2012
+.Dd October 19, 2012
.Dt PMC.SANDYBRIDGEUC 3
.Os
.Sh NAME
@@ -208,6 +208,7 @@ Counts the number of core-outgoing entries in the coherent tracker queue.
.Xr pmc.p5 3 ,
.Xr pmc.p6 3 ,
.Xr pmc.sandybridge 3 ,
+.Xr pmc.sandybridgexeon 3 ,
.Xr pmc.soft 3 ,
.Xr pmc.tsc 3 ,
.Xr pmc.ucf 3 ,
diff --git a/lib/libpmc/pmc.sandybridgexeon.3 b/lib/libpmc/pmc.sandybridgexeon.3
new file mode 100644
index 0000000..c62a82b
--- /dev/null
+++ b/lib/libpmc/pmc.sandybridgexeon.3
@@ -0,0 +1,1023 @@
+.\" Copyright (c) 2012 Hiren Panchasara <hiren.panchasara@gmail.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 THE AUTHOR 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 AUTHOR 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.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd October 18, 2012
+.Dt PMC.SANDYBRIDGEXEON 3
+.Os
+.Sh NAME
+.Nm pmc.sandybridgexeon
+.Nd measurement events for
+.Tn Intel
+.Tn Sandy Bridge Xeon
+family CPUs
+.Sh LIBRARY
+.Lb libpmc
+.Sh SYNOPSIS
+.In pmc.h
+.Sh DESCRIPTION
+.Tn Intel
+.Tn "Sandy Bridge Xeon"
+CPUs contain PMCs conforming to version 2 of the
+.Tn Intel
+performance measurement architecture.
+These CPUs may contain up to two classes of PMCs:
+.Bl -tag -width "Li PMC_CLASS_IAP"
+.It Li PMC_CLASS_IAF
+Fixed-function counters that count only one hardware event per counter.
+.It Li PMC_CLASS_IAP
+Programmable counters that may be configured to count one of a defined
+set of hardware events.
+.El
+.Pp
+The number of PMCs available in each class and their widths need to be
+determined at run time by calling
+.Xr pmc_cpuinfo 3 .
+.Pp
+Intel Sandy Bridge Xeon PMCs are documented in
+.Rs
+.%B "Intel(R) 64 and IA-32 Architectures Software Developer's Manual"
+.%T "Volume 3B: System Programming Guide, Part 2"
+.%N "Order Number: 253669-043US"
+.%D August 2012
+.%Q "Intel Corporation"
+.Re
+.Ss SANDYBRIDGE XEON FIXED FUNCTION PMCS
+These PMCs and their supported events are documented in
+.Xr pmc.iaf 3 .
+.Ss SANDYBRIDGE XEON PROGRAMMABLE PMCS
+The programmable PMCs support the following capabilities:
+.Bl -column "PMC_CAP_INTERRUPT" "Support"
+.It Em Capability Ta Em Support
+.It PMC_CAP_CASCADE Ta \&No
+.It PMC_CAP_EDGE Ta Yes
+.It PMC_CAP_INTERRUPT Ta Yes
+.It PMC_CAP_INVERT Ta Yes
+.It PMC_CAP_READ Ta Yes
+.It PMC_CAP_PRECISE Ta \&No
+.It PMC_CAP_SYSTEM Ta Yes
+.It PMC_CAP_TAGGING Ta \&No
+.It PMC_CAP_THRESHOLD Ta Yes
+.It PMC_CAP_USER Ta Yes
+.It PMC_CAP_WRITE Ta Yes
+.El
+.Ss Event Qualifiers
+Event specifiers for these PMCs support the following common
+qualifiers:
+.Bl -tag -width indent
+.It Li rsp= Ns Ar value
+Configure the Off-core Response bits.
+.Bl -tag -width indent
+.It Li REQ_DMND_DATA_RD
+Counts the number of demand and DCU prefetch data reads of full and partial
+cachelines as well as demand data page table entry cacheline reads. Does not
+count L2 data read prefetches or instruction fetches.
+.It Li REQ_DMND_RFO
+Counts the number of demand and DCU prefetch reads for ownership (RFO)
+requests generated by a write to data cacheline. Does not count L2 RFO
+prefetches.
+.It Li REQ_DMND_IFETCH
+Counts the number of demand and DCU prefetch instruction cacheline reads.
+Does not count L2 code read prefetches.
+.It Li REQ_WB
+Counts the number of writeback (modified to exclusive) transactions.
+.It Li REQ_PF_DATA_RD
+Counts the number of data cacheline reads generated by L2 prefetchers.
+.It Li REQ_PF_RFO
+Counts the number of RFO requests generated by L2 prefetchers.
+.It Li REQ_PF_IFETCH
+Counts the number of code reads generated by L2 prefetchers.
+.It Li REQ_PF_LLC_DATA_RD
+L2 prefetcher to L3 for loads.
+.It Li REQ_PF_LLC_RFO
+RFO requests generated by L2 prefetcher
+.It Li REQ_PF_LLC_IFETCH
+L2 prefetcher to L3 for instruction fetches.
+.It Li REQ_BUS_LOCKS
+Bus lock and split lock requests.
+.It Li REQ_STRM_ST
+Streaming store requests.
+.It Li REQ_OTHER
+Any other request that crosses IDI, including I/O.
+.It Li RES_ANY
+Catch all value for any response types.
+.It Li RES_SUPPLIER_NO_SUPP
+No Supplier Information available.
+.It Li RES_SUPPLIER_LLC_HITM
+M-state initial lookup stat in L3.
+.It Li RES_SUPPLIER_LLC_HITE
+E-state.
+.It Li RES_SUPPLIER_LLC_HITS
+S-state.
+.It Li RES_SUPPLIER_LLC_HITF
+F-state.
+.It Li RES_SUPPLIER_LOCAL
+Local DRAM Controller.
+.It Li RES_SNOOP_SNP_NONE
+No details on snoop-related information.
+.It Li RES_SNOOP_SNP_NO_NEEDED
+No snoop was needed to satisfy the request.
+.It Li RES_SNOOP_SNP_MISS
+A snoop was needed and it missed all snooped caches:
+-For LLC Hit, ReslHitl was returned by all cores
+-For LLC Miss, Rspl was returned by all sockets and data was returned from
+DRAM.
+.It Li RES_SNOOP_HIT_NO_FWD
+A snoop was needed and it hits in at least one snooped cache. Hit denotes a
+cache-line was valid before snoop effect. This includes:
+-Snoop Hit w/ Invalidation (LLC Hit, RFO)
+-Snoop Hit, Left Shared (LLC Hit/Miss, IFetch/Data_RD)
+-Snoop Hit w/ Invalidation and No Forward (LLC Miss, RFO Hit S)
+In the LLC Miss case, data is returned from DRAM.
+.It Li RES_SNOOP_HIT_FWD
+A snoop was needed and data was forwarded from a remote socket.
+This includes:
+-Snoop Forward Clean, Left Shared (LLC Hit/Miss, IFetch/Data_RD/RFT).
+.It Li RES_SNOOP_HITM
+A snoop was needed and it HitM-ed in local or remote cache. HitM denotes a
+cache-line was in modified state before effect as a results of snoop. This
+includes:
+-Snoop HitM w/ WB (LLC miss, IFetch/Data_RD)
+-Snoop Forward Modified w/ Invalidation (LLC Hit/Miss, RFO)
+-Snoop MtoS (LLC Hit, IFetch/Data_RD).
+.It Li RES_NON_DRAM
+Target was non-DRAM system address. This includes MMIO transactions.
+.El
+.It Li cmask= Ns Ar value
+Configure the PMC to increment only if the number of configured
+events measured in a cycle is greater than or equal to
+.Ar value .
+.It Li edge
+Configure the PMC to count the number of de-asserted to asserted
+transitions of the conditions expressed by the other qualifiers.
+If specified, the counter will increment only once whenever a
+condition becomes true, irrespective of the number of clocks during
+which the condition remains true.
+.It Li inv
+Invert the sense of comparison when the
+.Dq Li cmask
+qualifier is present, making the counter increment when the number of
+events per cycle is less than the value specified by the
+.Dq Li cmask
+qualifier.
+.It Li os
+Configure the PMC to count events happening at processor privilege
+level 0.
+.It Li usr
+Configure the PMC to count events occurring at privilege levels 1, 2
+or 3.
+.El
+.Pp
+If neither of the
+.Dq Li os
+or
+.Dq Li usr
+qualifiers are specified, the default is to enable both.
+.Ss Event Specifiers (Programmable PMCs)
+Sandy Bridge Xeon programmable PMCs support the following events:
+.Bl -tag -width indent
+.It Li LD_BLOCKS.DATA_UNKNOWN
+.Pq Event 03H , Umask 01H
+blocked loads due to store buffer blocks with unknown data.
+.It Li LD_BLOCKS.STORE_FORWARD
+.Pq Event 03H , Umask 02H
+loads blocked by overlapping with store buffer that cannot
+be forwarded .
+.It Li LD_BLOCKS.NO_SR
+.Pq Event 03H , Umask 08H
+# of Split loads blocked due to resource not available.
+.It Li LD_BLOCKS.ALL_BLOCK
+.Pq Event 03H , Umask 10H
+Number of cases where any load is blocked but has no
+DCU miss.
+.It Li MISALIGN_MEM_REF.LOADS
+.Pq Event 05H , Umask 01H
+Speculative cache-line split load uops dispatched to
+L1D.
+.It Li MISALIGN_MEM_REF.STORES
+.Pq Event 05H , Umask 02H
+Speculative cache-line split Store- address uops
+dispatchedto L1D.
+.It Li LD_BLOCKS_PARTIAL.ADDRESS_ALIAS
+.Pq Event 07H , Umask 01H
+False dependencies in MOB due to partial compare on
+address.
+.It Li LD_BLOCKS_PARTIAL.ALL_STALL_BLOCK
+.Pq Event 07H , Umask 08H
+The number of times that load operations are temporarily
+blocked because of older stores, with addresses that are
+not yet known. A load operation may incur more than one
+block of this type.
+.It Li TLB_LOAD_MISSES.MISS_CAUSES_A_WALK
+.Pq Event 08H , Umask 01H
+Misses in all TLB levels that cause a page walk of any
+page size.
+.It Li TLB_LOAD_MISSES.WALK_COMPLETED
+.Pq Event 08H , Umask 02H
+Misses in all TLB levels that caused page walk completed
+of any size.
+.It Li DTLB_LOAD_MISSES.WALK_DURATION
+.Pq Event 08H , Umask 04H
+Cycle PMH is busy with a walk.
+.It Li DTLB_LOAD_MISSES.STLB_HIT
+.Pq Event 08H , Umask 10H
+Number of cache load STLB hits. No page walk.
+.It Li INT_MISC.RECOVERY_CYCLES
+.Pq Event 0DH , Umask 03H
+Cycles waiting to recover after Machine Clears or EClear.
+Set Cmask= 1.
+.It Li INT_MISC.RAT_STALL_CYCLES
+.Pq Event 0DH , Umask 40H
+Cycles RAT external stall is sent to IDQ for this thread.
+.It Li UOPS_ISSUED.ANY
+.Pq Event 0EH , Umask 01H
+Increments each cycle the # of Uops issued by the
+RAT to RS.
+Set Cmask = 1, Inv = 1, Any= 1to count stalled cycles
+of this core.
+.It Li FP_COMP_OPS_EXE.X87
+.Pq Event 10H , Umask 01H
+Counts number of X87 uops executed.
+.It Li FP_COMP_OPS_EXE.SSE_FP_PACKED_DOUBLE
+.Pq Event 10H , Umask 10H
+Counts number of SSE* double precision FP packed
+uops executed.
+.It Li FP_COMP_OPS_EXE.SSE_FP_SCALAR_SINGLE
+.Pq Event 10H , Umask 20H
+Counts number of SSE* single precision FP scalar
+uops executed.
+.It Li FP_COMP_OPS_EXE.SSE_PACKED_SINGLE
+.Pq Event 10H , Umask 40H
+Counts number of SSE* single precision FP packed
+uops executed.
+.It Li FP_COMP_OPS_EXE.SSE_SCALAR_DOUBLE
+.Pq Event 10H , Umask 80H
+Counts number of SSE* double precision FP scalar
+uops executed.
+.It Li SIMD_FP_256.PACKED_SINGLE
+.Pq Event 11H , Umask 01H
+Counts 256-bit packed single-precision floating-
+point instructions.
+.It Li SIMD_FP_256.PACKED_DOUBLE
+.Pq Event 11H , Umask 02H
+Counts 256-bit packed double-precision floating-
+point instructions.
+.It Li ARITH.FPU_DIV_ACTIVE
+.Pq Event 14H , Umask 01H
+Cycles that the divider is active, includes INT and FP.
+Set 'edge =1, cmask=1' to count the number of
+divides.
+.It Li INSTS_WRITTEN_TO_IQ.INSTS
+.Pq Event 17H , Umask 01H
+Counts the number of instructions written into the
+IQ every cycle.
+.It Li L2_RQSTS.DEMAND_DATA_RD_HIT
+.Pq Event 24H , Umask 01H
+Demand Data Read requests that hit L2 cache.
+.It Li L2_RQSTS.ALL_DEMAND_DATA_RD
+.Pq Event 24H , Umask 03H
+Counts any demand and L1 HW prefetch data load
+requests to L2.
+.It Li L2_RQSTS.RFO_HITS
+.Pq Event 24H , Umask 04H
+Counts the number of store RFO requests that
+hit the L2 cache.
+.It Li L2_RQSTS.RFO_MISS
+.Pq Event 24H , Umask 08H
+Counts the number of store RFO requests that
+miss the L2 cache.
+.It Li L2_RQSTS.ALL_RFO
+.Pq Event 24H , Umask 0CH
+Counts all L2 store RFO requests.
+.It Li L2_RQSTS.CODE_RD_HIT
+.Pq Event 24H , Umask 10H
+Number of instruction fetches that hit the L2
+cache.
+.It Li L2_RQSTS.CODE_RD_MISS
+.Pq Event 24H , Umask 20H
+Number of instruction fetches that missed the L2
+cache.
+.It Li L2_RQSTS.ALL_CODE_RD
+.Pq Event 24H , Umask 30H
+Counts all L2 code requests.
+.It Li L2_RQSTS.PF_HIT
+.Pq Event 24H , Umask 40H
+Requests from L2 Hardware prefetcher that hit L2.
+.It Li L2_RQSTS.PF_MISS
+.Pq Event 24H , Umask 80H
+Requests from L2 Hardware prefetcher that missed
+L2.
+.It Li L2_RQSTS.ALL_PF
+.Pq Event 24H , Umask C0H
+Any requests from L2 Hardware prefetchers.
+.It Li L2_STORE_LOCK_RQSTS.MISS
+.Pq Event 27H , Umask 01H
+ROs that miss cache lines.
+.It Li L2_STORE_LOCK_RQSTS.HIT_E
+.Pq Event 27H , Umask 04H
+RFOs that hit cache lines in E state.
+.It Li L2_STORE_LOCK_RQSTS.HIT_M
+.Pq Event 27H , Umask 08H
+RFOs that hit cache lines in M state.
+.It Li L2_STORE_LOCK_RQSTS.ALL
+.Pq Event 27H , Umask 0FH
+RFOs that access cache lines in any state.
+.It Li L2_L1D_WB_RQSTS.MISS
+.Pq Event 28H , Umask 01H
+Not rejected writebacks from L1D to L2 cache lines
+that missed L2.
+.It Li L2_L1D_WB_RQSTS.HIT_S
+.Pq Event 28H , Umask 02H
+Not rejected writebacks from L1D to L2 cache lines
+in S state.
+.It Li L2_L1D_WB_RQSTS.HIT_E
+.Pq Event 28H , Umask 04H
+Not rejected writebacks from L1D to L2 cache lines
+in E state.
+.It Li L2_L1D_WB_RQSTS.HIT_M
+.Pq Event 28H , Umask 08H
+Not rejected writebacks from L1D to L2 cache lines
+in M state.
+.It Li L2_L1D_WB_RQSTS.ALL
+.Pq Event 28H , Umask 0FH
+Not rejected writebacks from L1D to L2 cache.
+.It Li LONGEST_LAT_CACHE.REFERENCE
+.Pq Event 2EH , Umask 4FH
+This event counts requests originating from the
+core that reference
+a cache line in the last level cache.
+.It Li LONGEST_LAT_CACHE.MISS
+.Pq Event 2EH , Umask 41H
+This event counts each cache miss condition for
+references to the last level cache.
+.It Li CPU_CLK_UNHALTED.THREAD_P
+.Pq Event 3CH , Umask 00H
+Counts the number of thread cycles while the
+thread is not in a halt state. The thread enters
+the halt state when it is running the HLT
+instruction. The core frequency may change from
+time to time due to power or thermal throttling.
+.It Li CPU_CLK_THREAD_UNHALTED.REF_XCLK
+.Pq Event 3CH , Umask 01H
+Increments at the frequency of XCLK (100 MHz)
+when not halted.
+.It Li L1D_PEND_MISS.PENDING
+.Pq Event 48H , Umask 01H
+Increments the number of outstanding L1D misses
+every cycle.
+Set Cmaks = 1 and Edge =1 to count occurrences.
+.It Li DTLB_STORE_MISSES.MISS_CAUSES_A_WALK
+.Pq Event 49H , Umask 01H
+Miss in all TLB levels causes an page walk of
+any page size (4K/2M/4M/1G).
+.It Li DTLB_STORE_MISSES.WALK_COMPLETED
+.Pq Event 49H , Umask 02H
+Miss in all TLB levels causes a page walk that
+completes of any page size (4K/2M/4M/1G).
+.It Li DTLB_STORE_MISSES.WALK_DURATION
+.Pq Event 49H , Umask 04H
+Cycles PMH is busy with this walk.
+.It Li DTLB_STORE_MISSES.STLB_HIT
+.Pq Event 49H , Umask 10H
+Store operations that miss the first TLB level
+but hit the second and do not cause page walks.
+.It Li LOAD_HIT_PRE.SW_PF
+.Pq Event 4CH , Umask 01H
+Not SW-prefetch load dispatches that hit fill
+buffer allocated for S/W prefetch.
+.It Li LOAD_HIT_PER.HW_PF
+.Pq Event 4CH , Umask 02H
+Not SW-prefetch load dispatches that hit fill
+buffer allocated for H/W prefetch.
+.It Li HW_PRE_REQ.DL1_MISS
+.Pq Event 4EH , Umask 02H
+Hardware Prefetch requests that miss the L1D
+cache. A request is being counted each time
+it access the cache & miss it, including if
+a block is applicable or if hit the Fill
+Buffer for example.
+.It Li L1D.REPLACEMENT
+.Pq Event 51H , Umask 01H
+Counts the number of lines brought into the
+L1 data cache.
+.It Li L1D.ALLOCATED_IN_M
+.Pq Event 51H , Umask 02H
+Counts the number of allocations of modified
+L1D cache lines.
+.It Li L1D.EVICTION
+.Pq Event 51H , Umask 04H
+Counts the number of modified lines evicted
+from the L1 data cache due to replacement.
+.It Li L1D.ALL_M_REPLACEMENT
+.Pq Event 51H , Umask 08H
+Cache lines in M state evicted out of L1D due
+to Snoop HitM or dirty line replacement.
+.It Li PARTIAL_RAT_STALLS.FLAGS_MERGE_UOP
+.Pq Event 59H , Umask 0CH
+Increments the number of flags-merge uops in
+flight each cycle.
+Set Cmask = 1 to count cycles.
+.It Li PARTIAL_RAT_STALLS.SLOW_LEA_WINDOW
+.Pq Event 59H , Umask 0FH
+Cycles with at least one slow LEA uop allocated.
+.It Li PARTIAL_RAT_STALLS.MUL_SINGLE_UOP
+.Pq Event 59H , Umask 40H
+Number of Multiply packed/scalar single precision
+uops allocated.
+.It Li RESOURCE_STALLS2.ALL_FL_EMPTY
+.Pq Event 5BH , Umask 0CH
+Cycles stalled due to free list empty.
+.It Li RESOURCE_STALLS2.ALL_PRF_CONTROL
+.Pq Event 5BH , Umask 0FH
+Cycles stalled due to control structures full for
+physical registers.
+.It Li RESOURCE_STALLS2.BOB_FULL
+.Pq Event 5BH , Umask 40H
+Cycles Allocator is stalled due Branch Order Buffer.
+.It Li RESOURCE_STALLS2.OOO_RSRC
+.Pq Event 5BH , Umask 4FH
+Cycles stalled due to out of order resources full.
+.It Li CPL_CYCLES.RING0
+.Pq Event 5CH , Umask 01H
+Unhalted core cycles when the thread is in ring 0.
+.It Li CPL_CYCLES.RING123
+.Pq Event 5CH , Umask 02H
+Unhalted core cycles when the thread is not in ring
+0.
+.It Li RS_EVENTS.EMPTY_CYCLES
+.Pq Event 5EH , Umask 01H
+Cycles the RS is empty for the thread.
+.It Li OFFCORE_REQUESTS_OUTSTANDING.DEMAND_DATA_RD
+.Pq Event 60H , Umask 01H
+Offcore outstanding Demand Data Read
+transactions in SQ to uncore. Set Cmask=1 to count
+cycles.
+.It Li OFFCORE_REQUESTS_OUTSTANDING.DEMAND_RFO
+.Pq Event 60H , Umask 04H
+Offcore outstanding RFO store transactions in SQ to
+uncore. Set Cmask=1 to count cycles.
+.It Li OFFCORE_REQUESTS_OUTSTANDING.ALL_DATA_RD
+.Pq Event 60H , Umask 08H
+Offcore outstanding cacheable data read
+transactions in SQ to uncore. Set Cmask=1 to count
+cycles.
+.It Li LOCK_CYCLES.SPLIT_LOCK_UC_LOCK_DURATION
+.Pq Event 63H , Umask 01H
+Cycles in which the L1D and L2 are locked, due to a
+UC lock or split lock.
+.It Li LOCK_CYCLES.CACHE_LOCK_DURATION
+.Pq Event 63H , Umask 02H
+Cycles in which the L1D is locked.
+.It Li IDQ.EMPTY
+.Pq Event 79H , Umask 02H
+Counts cycles the IDQ is empty.
+.It Li IDQ.MITE_UOPS
+.Pq Event 79H , Umask 04H
+Increment each cycle # of uops delivered to IDQ
+from MITE path.
+Set Cmask = 1 to count cycles.
+.It Li IDQ.DSB_UOPS
+.Pq Event 79H , Umask 08H
+Increment each cycle. # of uops delivered to IDQ
+from DSB path.
+Set Cmask = 1 to count cycles.
+.It Li IDQ.MS_DSB_UOPS
+.Pq Event 79H , Umask 10H
+Increment each cycle # of uops delivered to IDQ
+when MS busy by DSB. Set Cmask = 1 to count
+cycles MS is busy. Set Cmask=1 and Edge =1 to
+count MS activations.
+.It Li IDQ.MS_MITE_UOPS
+.Pq Event 79H , Umask 20H
+Increment each cycle # of uops delivered to IDQ
+when MS is busy by MITE. Set Cmask = 1 to count
+cycles.
+.It Li IDQ.MS_UOPS
+.Pq Event 79H , Umask 30H
+Increment each cycle # of uops delivered to IDQ
+from MS by either DSB or MITE. Set Cmask = 1 to
+count cycles.
+.It Li ICACHE.MISSES
+.Pq Event 80H , Umask 02H
+Number of Instruction Cache, Streaming Buffer and
+Victim Cache Misses. Includes UC accesses.
+.It Li ITLB_MISSES.MISS_CAUSES_A_WALK
+.Pq Event 85H , Umask 01H
+Misses in all ITLB levels that cause page walks.
+.It Li ITLB_MISSES.WALK_COMPLETED
+.Pq Event 85H , Umask 02H
+Misses in all ITLB levels that cause completed page
+walks.
+.It Li ITLB_MISSES.WALK_DURATION
+.Pq Event 85H , Umask 04H
+Cycle PMH is busy with a walk.
+.It Li ITLB_MISSES.STLB_HIT
+.Pq Event 85H , Umask 10H
+Number of cache load STLB hits. No page walk.
+.It Li ILD_STALL.LCP
+.Pq Event 87H , Umask 01H
+Stalls caused by changing prefix length of the
+instruction.
+.It Li ILD_STALL.IQ_FULL
+.Pq Event 87H , Umask 04H
+Stall cycles due to IQ is full.
+.It Li BR_INST_EXEC.COND
+.Pq Event 88H , Umask 01H
+Qualify conditional near branch instructions
+executed, but not necessarily retired.
+.It Li BR_INST_EXEC.DIRECT_JMP
+.Pq Event 88H , Umask 02H
+Qualify all unconditional near branch instructions
+excluding calls and indirect branches.
+.It Li BR_INST_EXEC.INDIRECT_JMP_NON_CALL_RET
+.Pq Event 88H , Umask 04H
+Qualify executed indirect near branch instructions
+that are not calls nor returns.
+.It Li BR_INST_EXEC.RETURN_NEAR
+.Pq Event 88H , Umask 08H
+Qualify indirect near branches that have a return
+mnemonic.
+.It Li BR_INST_EXEC.DIRECT_NEAR_CALL
+.Pq Event 88H , Umask 10H
+Qualify unconditional near call branch instructions,
+excluding non call branch, executed.
+.It Li BR_INST_EXEC.INDIRECT_NEAR_CALL
+.Pq Event 88H , Umask 20H
+Qualify indirect near calls, including both register
+and memory indirect, executed.
+.It Li BR_INST_EXEC.NONTAKEN
+.Pq Event 88H , Umask 40H
+Qualify non-taken near branches executed.
+.It Li BR_INST_EXEC.TAKEN
+.Pq Event 88H , Umask 80H
+Qualify taken near branches executed. Must
+combine with 01H,02H, 04H, 08H, 10H, 20H.
+.It Li BR_INST_EXE.ALL_BRANCHES
+.Pq Event 88H , Umask FFH
+Counts all near executed branches (not necessarily
+retired).
+.It Li BR_MISP_EXEC.COND
+.Pq Event 89H , Umask 01H
+Qualify conditional near branch instructions
+mispredicted.
+.It Li BR_MISP_EXEC.INDIRECT_JMP_NON_CALL_RET
+.Pq Event 89H , Umask 04H
+Qualify mispredicted indirect near branch
+instructions that are not calls nor returns.
+.It Li BR_MISP_EXEC.RETURN_NEAR
+.Pq Event 89H , Umask 08H
+Qualify mispredicted indirect near branches that
+have a return mnemonic.
+.It Li BR_MISP_EXEC.DIRECT_NEAR_CALL
+.Pq Event 89H , Umask 10H
+Qualify mispredicted unconditional near call branch
+instructions, excluding non call branch, executed.
+.It Li BR_MISP_EXEC.INDIRECT_NEAR_CALL
+.Pq Event 89H , Umask 20H
+Qualify mispredicted indirect near calls, including
+both register and memory indirect, executed.
+.It Li BR_MISP_EXEC.NONTAKEN
+.Pq Event 89H , Umask 40H
+Qualify mispredicted non-taken near branches
+executed,.
+.It Li BR_MISP_EXEC.TAKEN
+.Pq Event 89H , Umask 80H
+Qualify mispredicted taken near branches executed.
+Must combine with 01H,02H, 04H, 08H, 10H, 20H
+.It Li BR_MISP_EXEC.ALL_BRANCHES
+.Pq Event 89H , Umask FFH
+Counts all near executed branches (not necessarily
+retired).
+.It Li IDQ_UOPS_NOT_DELIVERED.CORE
+.Pq Event 9CH , Umask 01H
+Count number of non-delivered uops to RAT per
+thread.
+.It Li UOPS_DISPATCHED_PORT.PORT_0
+.Pq Event A1H , Umask 01H
+Cycles which a Uop is dispatched on port 0.
+.It Li UOPS_DISPATCHED_PORT.PORT_1
+.Pq Event A1H , Umask 02H
+Cycles which a Uop is dispatched on port 1.
+.It Li UOPS_DISPATCHED_PORT.PORT_2_LD
+.Pq Event A1H , Umask 04H
+Cycles which a load uop is dispatched on port 2.
+.It Li UOPS_DISPATCHED_PORT.PORT_2_STA
+.Pq Event A1H , Umask 08H
+Cycles which a store address uop is dispatched on
+port 2.
+.It Li UOPS_DISPATCHED_PORT.PORT_2
+.Pq Event A1H , Umask 0CH
+Cycles which a Uop is dispatched on port 2.
+.It Li UOPS_DISPATCHED_PORT.PORT_3_LD
+.Pq Event A1H , Umask 10H
+Cycles which a load uop is dispatched on port 3.
+.It Li UOPS_DISPATCHED_PORT.PORT_3_STA
+.Pq Event A1H , Umask 20H
+Cycles which a store address uop is dispatched on
+port 3.
+.It Li UOPS_DISPATCHED_PORT.PORT_3
+.Pq Event A1H , Umask 30H
+Cycles which a Uop is dispatched on port 3.
+.It Li UOPS_DISPATCHED_PORT.PORT_4
+.Pq Event A1H , Umask 40H
+Cycles which a Uop is dispatched on port 4.
+.It Li UOPS_DISPATCHED_PORT.PORT_5
+.Pq Event A1H , Umask 80H
+Cycles which a Uop is dispatched on port 5.
+.It Li RESOURCE_STALLS.ANY
+.Pq Event A2H , Umask 01H
+Cycles Allocation is stalled due to Resource Related
+reason.
+.It Li RESOURCE_STALLS.LB
+.Pq Event A2H , Umask 01H
+Counts the cycles of stall due to lack of load buffers.
+.It Li RESOURCE_STALLS.RS
+.Pq Event A2H , Umask 04H
+Cycles stalled due to no eligible RS entry available.
+.It Li RESOURCE_STALLS.SB
+.Pq Event A2H , Umask 08H
+Cycles stalled due to no store buffers available. (not
+including draining form sync).
+.It Li RESOURCE_STALLS.ROB
+.Pq Event A2H , Umask 10H
+Cycles stalled due to re-order buffer full.
+.It Li RESOURCE_STALLS.FCSW
+.Pq Event A2H , Umask 20H
+Cycles stalled due to writing the FPU control word.
+.It Li RESOURCE_STALLS.MXCSR
+.Pq Event A2H , Umask 40H
+Cycles stalled due to the MXCSR register rename
+occurring to close to a previous MXCSR rename.
+.It Li RESOURCE_STALLS.OTHER
+.Pq Event A2H , Umask 80H
+Cycles stalled while execution was stalled due to
+other resource issues.
+.It Li CYCLE_ACTIVITY.CYCLES_L2_PENDING
+.Pq Event A3H , Umask 01H
+Cycles with pending L2 miss loads. Set AnyThread
+to count per core.
+.It Li CYCLE_ACTIVITY.CYCLES_L1D_PENDING
+.Pq Event A3H , Umask 02H
+Cycles with pending L1 cache miss loads.Set
+AnyThread to count per core.
+.It Li CYCLE_ACTIVITY.CYCLES_NO_DISPATCH
+.Pq Event A3H , Umask 04H
+Cycles of dispatch stalls. Set AnyThread to count per
+core.
+.It Li DSB2MITE_SWITCHES.COUNT
+.Pq Event ABH , Umask 01H
+Number of DSB to MITE switches.
+.It Li DSB2MITE_SWITCHES.PENALTY_CYCLES
+.Pq Event ABH , Umask 02H
+Cycles DSB to MITE switches caused delay.
+.It Li DSB_FILL.OTHER_CANCEL
+.Pq Event ACH , Umask 02H
+Cases of cancelling valid DSB fill not because of
+exceeding way limit.
+.It Li DSB_FILL.EXCEED_DSB_LINES
+.Pq Event ACH , Umask 08H
+DSB Fill encountered > 3 DSB lines.
+.It Li DSB_FILL.ALL_CANCEL
+.Pq Event ACH , Umask 0AH
+Cases of cancelling valid Decode Stream Buffer
+(DSB) fill not because of exceeding way limit.
+.It Li ITLB.ITLB_FLUSH
+.Pq Event AEH , Umask 01H
+Counts the number of ITLB flushes, includes
+4k/2M/4M pages.
+.It Li OFFCORE_REQUESTS.DEMAND_DATA_RD
+.Pq Event B0H , Umask 01H
+Demand data read requests sent to uncore.
+.It Li OFFCORE_REQUESTS.DEMAND_RFO
+.Pq Event B0H , Umask 04H
+Demand RFO read requests sent to uncore, including
+regular RFOs, locks, ItoM.
+.It Li OFFCORE_REQUESTS.ALL_DATA_RD
+.Pq Event B0H , Umask 08H
+Data read requests sent to uncore (demand and
+prefetch).
+.It Li UOPS_DISPATCHED.THREAD
+.Pq Event B1H , Umask 01H
+Counts total number of uops to be dispatched per-
+thread each cycle. Set Cmask = 1, INV =1 to count
+stall cycles.
+.It Li UOPS_DISPATCHED.CORE
+.Pq Event B1H , Umask 02H
+Counts total number of uops to be dispatched per-
+core each cycle.
+.It Li OFFCORE_REQUESTS_BUFFER.SQ_FULL
+.Pq Event B2H , Umask 01H
+Offcore requests buffer cannot take more entries
+for this thread core.
+.It Li AGU_BYPASS_CANCEL.COUNT
+.Pq Event B6H , Umask 01H
+Counts executed load operations with all the
+following traits: 1. addressing of the format [base +
+offset], 2. the offset is between 1 and 2047, 3. the
+address specified in the base register is in one page
+and the address [base+offset] is in another page.
+.It Li OFF_CORE_RESPONSE_0
+.Pq Event B7H , Umask 01H
+(Event B7H, Umask 01H) Off-core Response Performance
+Monitoring; PMC0 only. Requires programming MSR 01A6H
+.It Li OFF_CORE_RESPONSE_1
+.Pq Event BBH , Umask 01H
+(Event BBH, Umask 01H) Off-core Response Performance
+Monitoring; PMC3 only. Requires programming MSR 01A7H
+.It Li TLB_FLUSH.DTLB_THREAD
+.Pq Event BDH , Umask 01H
+DTLB flush attempts of the thread-specific entries.
+.It Li TLB_FLUSH.STLB_ANY
+.Pq Event BDH , Umask 20H
+Count number of STLB flush attempts.
+.It Li L1D_BLOCKS.BANK_CONFLICT_CYCLES
+.Pq Event BFH , Umask 05H
+Cycles when dispatched loads are cancelled due to
+L1D bank conflicts with other load ports.
+.It Li INST_RETIRED.ANY_P
+.Pq Event C0H , Umask 00H
+Number of instructions at retirement.
+.It Li INST_RETIRED.ALL
+.Pq Event C0H , Umask 01H
+Precise instruction retired event with HW to reduce
+effect of PEBS shadow in IP distribution.
+.It Li OTHER_ASSISTS.ITLB_MISS_RETIRED
+.Pq Event C1H , Umask 02H
+Instructions that experienced an ITLB miss.
+.It Li OTHER_ASSISTS.AVX_STORE
+.Pq Event C1H , Umask 08H
+Number of assists associated with 256-bit AVX
+store operations.
+.It Li OTHER_ASSISTS.AVX_TO_SSE
+.Pq Event C1H , Umask 10H
+Number of transitions from AVX-256 to legacy SSE
+when penalty applicable.
+.It Li OTHER_ASSISTS.SSE_TO_AVX
+.Pq Event C1H , Umask 20H
+Number of transitions from SSE to AVX-256 when
+penalty applicable.
+.It Li UOPS_RETIRED.ALL
+.Pq Event C2H , Umask 01H
+Counts the number of micro-ops retired, Use
+cmask=1 and invert to count active cycles or stalled
+cycles.
+.It Li UOPS_RETIRED.RETIRE_SLOTS
+.Pq Event C2H , Umask 02H
+Counts the number of retirement slots used each
+cycle.
+.It Li MACHINE_CLEARS.MEMORY_ORDERING
+.Pq Event C3H , Umask 02H
+Counts the number of machine clears due to
+memory order conflicts.
+.It Li MACHINE_CLEARS.SMC
+.Pq Event C3H , Umask 04H
+Counts the number of times that a program writes
+to a code section.
+.It Li MACHINE_CLEARS.MASKMOV
+.Pq Event C3H , Umask 20H
+Counts the number of executed AVX masked load
+operations that refer to an illegal address range
+with the mask bits set to 0.
+.It Li BR_INST_RETIRED.ALL_BRANCH
+.Pq Event C4H , Umask 00H
+Branch instructions at retirement.
+.It Li BR_INST_RETIRED.CONDITIONAL
+.Pq Event C4H , Umask 01H
+Counts the number of conditional branch
+instructions retired.
+.It Li BR_INST_RETIRED.NEAR_CALL
+.Pq Event C4H , Umask 02H
+Direct and indirect near call instructions retired.
+.It Li BR_INST_RETIRED.ALL_BRANCHES
+.Pq Event C4H , Umask 04H
+Counts the number of branch instructions retired.
+.It Li BR_INST_RETIRED.NEAR_RETURN
+.Pq Event C4H , Umask 08H
+Counts the number of near return instructions
+retired.
+.It Li BR_INST_RETIRED.NOT_TAKEN
+.Pq Event C4H , Umask 10H
+Counts the number of not taken branch instructions
+retired.
+.It Li BR_INST_RETIRED.NEAR_TAKEN
+.Pq Event C4H , Umask 20H
+Number of near taken branches retired.
+.It Li BR_INST_RETIRED.FAR_BRANCH
+.Pq Event C4H , Umask 40H
+Number of far branches retired.
+.It Li BR_MISP_RETIRED.ALL_BRANCHES
+.Pq Event C5H , Umask 00H
+Mispredicted branch instructions at retirement.
+.It Li BR_MISP_RETIRED.CONDITIONAL
+.Pq Event C5H , Umask 01H
+Mispredicted conditional branch instructions retired.
+.It Li BR_MISP_RETIRED.NEAR_CALL
+.Pq Event C5H , Umask 02H
+Direct and indirect mispredicted near call
+instructions retired.
+.It Li BR_MISP_RETIRED.ALL_BRANCHES
+.Pq Event C5H , Umask 04H
+Mispredicted macro branch instructions retired.
+.It Li BR_MISP_RETIRED.NOT_TAKEN
+.Pq Event C5H , Umask 10H
+Mispredicted not taken branch instructions retired.
+.It Li BR_MISP_RETIRED.TAKEN
+.Pq Event C5H , Umask 20H
+Mispredicted taken branch instructions retired.
+.It Li FP_ASSIST.X87_OUTPUT
+.Pq Event CAH , Umask 02H
+Number of X87 assists due to output value.
+.It Li FP_ASSIST.X87_INPUT
+.Pq Event CAH , Umask 04H
+Number of X87 assists due to input value.
+.It Li FP_ASSIST.SIMD_OUTPUT
+.Pq Event CAH , Umask 08H
+ Number of SIMD FP assists due to output values.
+.It Li FP_ASSIST.SIMD_INPUT
+.Pq Event CAH , Umask 10H
+Number of SIMD FP assists due to input values.
+.It Li FP_ASSIST.ANY 1EH
+.Pq Event CAH , Umask
+Cycles with any input/output SSE* or FP assists.
+.It Li ROB_MISC_EVENTS.LBR_INSERTS
+.Pq Event CCH , Umask 20H
+Count cases of saving new LBR records by
+hardware.
+.It Li MEM_TRANS_RETIRED.LOAD_LATENCY
+.Pq Event CDH , Umask 01H
+Sample loads with specified latency threshold.
+PMC3 only.
+.It Li MEM_TRANS_RETIRED.PRECISE_STORE
+.Pq Event CDH , Umask 02H
+Sample stores and collect precise store operation
+via PEBS record. PMC3 only.
+.It Li MEM_UOP_RETIRED.LOADS
+.Pq Event D0H , Umask 10H
+Qualify retired memory uops that are loads.
+Combine with umask 10H, 20H, 40H, 80H.
+.It Li MEM_UOP_RETIRED.STORES
+.Pq Event D0H , Umask 02H
+Qualify retired memory uops that are stores.
+Combine with umask 10H, 20H, 40H, 80H.
+.It Li MEM_UOP_RETIRED.STLB_MISS
+.Pq Event D0H , Umask
+Qualify retired memory uops with STLB miss. Must
+combine with umask 01H, 02H, to produce counts.
+.It Li MEM_UOP_RETIRED.LOCK
+.Pq Event D0H , Umask
+Qualify retired memory uops with lock. Must
+combine with umask 01H, 02H, to produce counts.
+.It Li MEM_UOP_RETIRED.SPLIT
+.Pq Event D0H , Umask
+Qualify retired memory uops with line split. Must
+combine with umask 01H, 02H, to produce counts.
+.It Li MEM_UOP_RETIRED_ALL
+.Pq Event D0H , Umask
+Qualify any retired memory uops. Must combine
+with umask 01H, 02H, to produce counts.
+.It Li MEM_LOAD_UOPS_RETIRED.L1_HIT
+.Pq Event D1H , Umask 01H
+Retired load uops with L1 cache hits as data
+sources.
+.It Li MEM_LOAD_UOPS_RETIRED.L2_HIT
+.Pq Event D1H , Umask 02H
+Retired load uops with L2 cache hits as data
+sources.
+.It Li MEM_LOAD_UOPS_RETIRED.LLC_HIT
+.Pq Event D1H , Umask 04H
+Retired load uops which data sources were data hits
+in LLC without snoops required.
+.It Li MEM_LOAD_UOPS_RETIRED.LLC_MISS
+.Pq Event D1H , Umask 20H
+Retired load uops which data sources were data
+missed LLC (excluding unknown data source).
+.It Li MEM_LOAD_UOPS_RETIRED.HIT_LFB
+.Pq Event D1H , Umask 40H
+Retired load uops which data sources were load
+uops missed L1 but hit FB due to preceding miss to
+the same cache line with data not ready.
+.It Li MEM_LOAD_UOPS_MISC_RETIRED.LLC_MISS
+.Pq Event D4H , Umask 02H
+Retired load uops with unknown information as data
+source in cache serviced the load.
+.It Li BACLEARS.ANY
+.Pq Event E6H , Umask 01H
+Counts the number of times the front end is re-
+steered, mainly when the BPU cannot provide a
+correct prediction and this is corrected by other
+branch handling mechanisms at the front end.
+.It Li L2_TRANS.DEMAND_DATA_RD
+.Pq Event F0H , Umask 01H
+Demand Data Read requests that access L2 cache.
+.It Li L2_TRANS.RFO
+.Pq Event F0H , Umask 02H
+RFO requests that access L2 cache.
+.It Li L2_TRANS.CODE_RD
+.Pq Event F0H , Umask 04H
+L2 cache accesses when fetching instructions.
+.It Li L2_TRANS.ALL_PF
+.Pq Event F0H , Umask 08H
+L2 or LLC HW prefetches that access L2 cache.
+.It Li L2_TRANS.L1D_WB
+.Pq Event F0H , Umask 10H
+L1D writebacks that access L2 cache.
+.It Li L2_TRANS.L2_FILL
+.Pq Event F0H , Umask 20H
+L2 fill requests that access L2 cache.
+.It Li L2_TRANS.L2_WB
+.Pq Event F0H , Umask 40H
+L2 writebacks that access L2 cache.
+.It Li L2_TRANS.ALL_REQUESTS
+.Pq Event F0H , Umask 80H
+Transactions accessing L2 pipe.
+.It Li L2_LINES_IN.I
+.Pq Event F1H , Umask 01H
+L2 cache lines in I state filling L2.
+.It Li L2_LINES_IN.S
+.Pq Event F1H , Umask 02H
+L2 cache lines in S state filling L2.
+.It Li L2_LINES_IN.E
+.Pq Event F1H , Umask 04H
+L2 cache lines in E state filling L2.
+.It Li L2_LINES-IN.ALL
+.Pq Event F1H , Umask 07H
+L2 cache lines filling L2.
+.It Li L2_LINES_OUT.DEMAND_CLEAN
+.Pq Event F2H , Umask 01H
+Clean L2 cache lines evicted by demand.
+.It Li L2_LINES_OUT.DEMAND_DIRTY
+.Pq Event F2H , Umask 02H
+Dirty L2 cache lines evicted by demand.
+.It Li L2_LINES_OUT.PF_CLEAN
+.Pq Event F2H , Umask 04H
+Clean L2 cache lines evicted by L2 prefetch.
+.It Li L2_LINES_OUT.PF_DIRTY
+.Pq Event F2H , Umask 08H
+Dirty L2 cache lines evicted by L2 prefetch.
+.It Li L2_LINES_OUT.DIRTY_ALL
+.Pq Event F2H , Umask 0AH
+Dirty L2 cache lines filling the L2.
+.It Li SQ_MISC.SPLIT_LOCK
+.Pq Event F4H , Umask 10H
+Split locks in SQ.
+.El
+.Sh SEE ALSO
+.Xr pmc 3 ,
+.Xr pmc.atom 3 ,
+.Xr pmc.core 3 ,
+.Xr pmc.iaf 3 ,
+.Xr pmc.ucf 3 ,
+.Xr pmc.k7 3 ,
+.Xr pmc.k8 3 ,
+.Xr pmc.p4 3 ,
+.Xr pmc.p5 3 ,
+.Xr pmc.p6 3 ,
+.Xr pmc.corei7 3 ,
+.Xr pmc.corei7uc 3 ,
+.Xr pmc.ivybridge 3 ,
+.Xr pmc.sandybridge 3 ,
+.Xr pmc.sandybridgeuc 3 ,
+.Xr pmc.westmere 3 ,
+.Xr pmc.westmereuc 3 ,
+.Xr pmc.soft 3 ,
+.Xr pmc.tsc 3 ,
+.Xr pmc_cpuinfo 3 ,
+.Xr pmclog 3 ,
+.Xr hwpmc 4
+.Sh HISTORY
+The
+.Nm pmc
+library first appeared in
+.Fx 6.0 .
+.Sh AUTHORS
+The
+.Lb libpmc
+library was written by
+.An "Joseph Koshy"
+.Aq jkoshy@FreeBSD.org .
+The support for the Sandy Bridge Xeon
+microarchitecture was written by
+.An "Hiren Panchasara"
+.Aq hiren.panchasara@gmail.com .
diff --git a/lib/libproc/Makefile b/lib/libproc/Makefile
index c02e719..4449c06 100644
--- a/lib/libproc/Makefile
+++ b/lib/libproc/Makefile
@@ -1,5 +1,7 @@
# $FreeBSD$
+.include <bsd.own.mk>
+
LIB= proc
SRCS= proc_bkpt.c \
@@ -13,6 +15,14 @@ INCS= libproc.h
CFLAGS+= -I${.CURDIR}
+.if ${MK_LIBCPLUSPLUS} != "no"
+LDADD+= -lcxxrt
+DPADD+= ${LIBCXXRT}
+.else
+LDADD+= -lsupc++
+DPADD+= ${LIBSTDCPLUSPLUS}
+.endif
+
SHLIB_MAJOR= 2
WITHOUT_MAN=
diff --git a/lib/libproc/proc_sym.c b/lib/libproc/proc_sym.c
index 1d56df0..4bef7f0 100644
--- a/lib/libproc/proc_sym.c
+++ b/lib/libproc/proc_sym.c
@@ -46,9 +46,31 @@
#include "_libproc.h"
+extern char *__cxa_demangle(const char *, char *, size_t *, int *);
+
static void proc_rdl2prmap(rd_loadobj_t *, prmap_t *);
static void
+demangle(const char *symbol, char *buf, size_t len)
+{
+ char *dembuf;
+ size_t demlen = len;
+
+ dembuf = malloc(len);
+ if (!dembuf)
+ goto fail;
+ dembuf = __cxa_demangle(symbol, dembuf, &demlen, NULL);
+ if (!dembuf)
+ goto fail;
+ strlcpy(buf, dembuf, len);
+ free(dembuf);
+
+ return;
+fail:
+ strlcpy(buf, symbol, len);
+}
+
+static void
proc_rdl2prmap(rd_loadobj_t *rdl, prmap_t *map)
{
map->pr_vaddr = rdl->rdl_saddr;
@@ -254,7 +276,7 @@ proc_addr2sym(struct proc_handle *p, uintptr_t addr, char *name,
*/
if ((data = elf_getdata(dynsymscn, NULL)) == NULL) {
DPRINTF("ERROR: elf_getdata() failed");
- goto err2;
+ goto symtab;
}
i = 0;
while (gelf_getsym(data, i++, &sym) != NULL) {
@@ -266,7 +288,10 @@ proc_addr2sym(struct proc_handle *p, uintptr_t addr, char *name,
if (addr >= rsym && addr <= (rsym + sym.st_size)) {
s = elf_strptr(e, dynsymstridx, sym.st_name);
if (s) {
- strlcpy(name, s, namesz);
+ if (s[0] == '_' && s[1] == 'Z' && s[2])
+ demangle(s, name, namesz);
+ else
+ strlcpy(name, s, namesz);
memcpy(symcopy, &sym, sizeof(sym));
/*
* DTrace expects the st_value to contain
@@ -274,11 +299,11 @@ proc_addr2sym(struct proc_handle *p, uintptr_t addr, char *name,
* the function.
*/
symcopy->st_value = rsym;
- error = 0;
goto out;
}
}
}
+symtab:
/*
* Iterate over the Symbols Table to find the symbol.
* Then look up the string name in STRTAB (.dynstr)
@@ -302,7 +327,10 @@ proc_addr2sym(struct proc_handle *p, uintptr_t addr, char *name,
if (addr >= rsym && addr <= (rsym + sym.st_size)) {
s = elf_strptr(e, symtabstridx, sym.st_name);
if (s) {
- strlcpy(name, s, namesz);
+ if (s[0] == '_' && s[1] == 'Z' && s[2])
+ demangle(s, name, namesz);
+ else
+ strlcpy(name, s, namesz);
memcpy(symcopy, &sym, sizeof(sym));
/*
* DTrace expects the st_value to contain
@@ -430,18 +458,17 @@ proc_name2sym(struct proc_handle *p, const char *object, const char *symbol,
* Iterate over the Dynamic Symbols table to find the symbol.
* Then look up the string name in STRTAB (.dynstr)
*/
- if ((data = elf_getdata(dynsymscn, NULL)) == NULL) {
+ if ((data = elf_getdata(dynsymscn, NULL))) {
DPRINTF("ERROR: elf_getdata() failed");
- goto err2;
- }
- i = 0;
- while (gelf_getsym(data, i++, &sym) != NULL) {
- s = elf_strptr(e, dynsymstridx, sym.st_name);
- if (s && strcmp(s, symbol) == 0) {
- memcpy(symcopy, &sym, sizeof(sym));
- symcopy->st_value = map->pr_vaddr + sym.st_value;
- error = 0;
- goto out;
+ i = 0;
+ while (gelf_getsym(data, i++, &sym) != NULL) {
+ s = elf_strptr(e, dynsymstridx, sym.st_name);
+ if (s && strcmp(s, symbol) == 0) {
+ memcpy(symcopy, &sym, sizeof(sym));
+ symcopy->st_value = map->pr_vaddr + sym.st_value;
+ error = 0;
+ goto out;
+ }
}
}
/*
@@ -450,17 +477,15 @@ proc_name2sym(struct proc_handle *p, const char *object, const char *symbol,
*/
if (symtabscn == NULL)
goto err2;
- if ((data = elf_getdata(symtabscn, NULL)) == NULL) {
- DPRINTF("ERROR: elf_getdata() failed");
- goto err2;
- }
- i = 0;
- while (gelf_getsym(data, i++, &sym) != NULL) {
- s = elf_strptr(e, symtabstridx, sym.st_name);
- if (s && strcmp(s, symbol) == 0) {
- memcpy(symcopy, &sym, sizeof(sym));
- error = 0;
- goto out;
+ if ((data = elf_getdata(symtabscn, NULL))) {
+ i = 0;
+ while (gelf_getsym(data, i++, &sym) != NULL) {
+ s = elf_strptr(e, symtabstridx, sym.st_name);
+ if (s && strcmp(s, symbol) == 0) {
+ memcpy(symcopy, &sym, sizeof(sym));
+ error = 0;
+ goto out;
+ }
}
}
out:
diff --git a/lib/libproc/test/t1-bkpt/t1-bkpt.c b/lib/libproc/test/t1-bkpt/t1-bkpt.c
index 6b4e2fa..37a9fcf 100644
--- a/lib/libproc/test/t1-bkpt/t1-bkpt.c
+++ b/lib/libproc/test/t1-bkpt/t1-bkpt.c
@@ -50,12 +50,12 @@ t1_bkpt_d()
unsigned long saved;
proc_create("./t1-bkpt", targv, NULL, NULL, &phdl);
- proc_bkptset(phdl, (uintptr_t)t1_bkpt_t, &saved);
+ assert(proc_bkptset(phdl, (uintptr_t)t1_bkpt_t, &saved) == 0);
proc_continue(phdl);
- assert(WIFSTOPPED(proc_wstatus(phdl)));
+ assert(proc_wstatus(phdl) == PS_STOP);
proc_bkptexec(phdl, saved);
proc_continue(phdl);
- proc_wait(phdl);
+ proc_wstatus(phdl);
proc_free(phdl);
}
diff --git a/lib/libproc/test/t3-name2sym/t3-name2sym.c b/lib/libproc/test/t3-name2sym/t3-name2sym.c
index 6d90a48..0be8653 100644
--- a/lib/libproc/test/t3-name2sym/t3-name2sym.c
+++ b/lib/libproc/test/t3-name2sym/t3-name2sym.c
@@ -33,6 +33,7 @@
#include <stdio.h>
#include <libproc.h>
#include <gelf.h>
+#include <string.h>
int
main(int argc, char *argv[])
diff --git a/lib/libprocstat/Makefile b/lib/libprocstat/Makefile
index 9804483..a29afc7 100644
--- a/lib/libprocstat/Makefile
+++ b/lib/libprocstat/Makefile
@@ -8,8 +8,6 @@ SRCS= cd9660.c \
common_kvm.c \
libprocstat.c \
msdosfs.c \
- ntfs.c \
- smbfs.c \
udf.c
VERSION_DEF= ${.CURDIR}/Versions.def
@@ -24,11 +22,6 @@ LDADD= -lkvm -lutil
MAN= libprocstat.3
-.if ${MK_NCP} != "no"
-CFLAGS+= -DLIBPROCSTAT_NWFS
-SRCS+= nwfs.c
-.endif
-
# XXX This is a hack.
.if ${MK_CDDL} != "no"
CFLAGS+= -DLIBPROCSTAT_ZFS
diff --git a/lib/libprocstat/common_kvm.h b/lib/libprocstat/common_kvm.h
index d0b5307..d5e08e1 100644
--- a/lib/libprocstat/common_kvm.h
+++ b/lib/libprocstat/common_kvm.h
@@ -41,9 +41,6 @@ int devfs_filestat(kvm_t *kd, struct vnode *vp, struct vnstat *vn);
int isofs_filestat(kvm_t *kd, struct vnode *vp, struct vnstat *vn);
int msdosfs_filestat(kvm_t *kd, struct vnode *vp, struct vnstat *vn);
int nfs_filestat(kvm_t *kd, struct vnode *vp, struct vnstat *vn);
-int ntfs_filestat(kvm_t *kd, struct vnode *vp, struct vnstat *vn);
-int nwfs_filestat(kvm_t *kd, struct vnode *vp, struct vnstat *vn);
-int smbfs_filestat(kvm_t *kd, struct vnode *vp, struct vnstat *vn);
int udf_filestat(kvm_t *kd, struct vnode *vp, struct vnstat *vn);
int ufs_filestat(kvm_t *kd, struct vnode *vp, struct vnstat *vn);
int zfs_filestat(kvm_t *kd, struct vnode *vp, struct vnstat *vn);
diff --git a/lib/libprocstat/libprocstat.c b/lib/libprocstat/libprocstat.c
index 56562e1..9d9c111 100644
--- a/lib/libprocstat/libprocstat.c
+++ b/lib/libprocstat/libprocstat.c
@@ -184,15 +184,18 @@ procstat_getprocs(struct procstat *procstat, int what, int arg,
struct kinfo_proc *p0, *p;
size_t len;
int name[4];
+ int cnt;
int error;
assert(procstat);
assert(count);
p = NULL;
if (procstat->type == PROCSTAT_KVM) {
- p0 = kvm_getprocs(procstat->kd, what, arg, count);
- if (p0 == NULL || count == 0)
+ *count = 0;
+ p0 = kvm_getprocs(procstat->kd, what, arg, &cnt);
+ if (p0 == NULL || cnt <= 0)
return (NULL);
+ *count = cnt;
len = *count * sizeof(*p);
p = malloc(len);
if (p == NULL) {
@@ -970,11 +973,6 @@ procstat_get_vnode_info_kvm(kvm_t *kd, struct filestat *fst,
FSTYPE(isofs),
FSTYPE(msdosfs),
FSTYPE(nfs),
- FSTYPE(ntfs),
-#ifdef LIBPROCSTAT_NWFS
- FSTYPE(nwfs),
-#endif
- FSTYPE(smbfs),
FSTYPE(udf),
FSTYPE(ufs),
#ifdef LIBPROCSTAT_ZFS
diff --git a/lib/libprocstat/libprocstat.h b/lib/libprocstat/libprocstat.h
index c00a179..662ea37 100644
--- a/lib/libprocstat/libprocstat.h
+++ b/lib/libprocstat/libprocstat.h
@@ -144,6 +144,7 @@ struct sockstat {
STAILQ_HEAD(filestat_list, filestat);
+__BEGIN_DECLS
void procstat_close(struct procstat *procstat);
void procstat_freeprocs(struct procstat *procstat, struct kinfo_proc *p);
void procstat_freefiles(struct procstat *procstat,
@@ -164,5 +165,6 @@ int procstat_get_vnode_info(struct procstat *procstat, struct filestat *fst,
struct vnstat *vn, char *errbuf);
struct procstat *procstat_open_sysctl(void);
struct procstat *procstat_open_kvm(const char *nlistf, const char *memf);
+__END_DECLS
#endif /* !_LIBPROCSTAT_H_ */
diff --git a/lib/librpcsec_gss/svc_rpcsec_gss.c b/lib/librpcsec_gss/svc_rpcsec_gss.c
index d0599be..e110a5f 100644
--- a/lib/librpcsec_gss/svc_rpcsec_gss.c
+++ b/lib/librpcsec_gss/svc_rpcsec_gss.c
@@ -140,8 +140,8 @@ TAILQ_HEAD(svc_rpc_gss_client_list, svc_rpc_gss_client);
#define CLIENT_HASH_SIZE 256
#define CLIENT_MAX 128
-struct svc_rpc_gss_client_list svc_rpc_gss_client_hash[CLIENT_HASH_SIZE];
-struct svc_rpc_gss_client_list svc_rpc_gss_clients;
+static struct svc_rpc_gss_client_list svc_rpc_gss_client_hash[CLIENT_HASH_SIZE];
+static struct svc_rpc_gss_client_list svc_rpc_gss_clients;
static size_t svc_rpc_gss_client_count;
static uint32_t svc_rpc_gss_next_clientid = 1;
diff --git a/lib/libstand/nandfs.c b/lib/libstand/nandfs.c
index 67e2fea..d5fcb9d 100644
--- a/lib/libstand/nandfs.c
+++ b/lib/libstand/nandfs.c
@@ -175,7 +175,7 @@ static int
nandfs_find_super_block(struct nandfs *fs, struct open_file *f)
{
struct nandfs_super_block *sb;
- int i, j, n;
+ int i, j, n, s;
int sectors_to_read, error;
sb = malloc(fs->nf_sectorsize);
@@ -196,23 +196,22 @@ nandfs_find_super_block(struct nandfs *fs, struct open_file *f)
continue;
}
n = fs->nf_sectorsize / sizeof(struct nandfs_super_block);
+ s = 0;
if ((i * fs->nf_sectorsize) % fs->nf_fsdata->f_erasesize == 0) {
if (fs->nf_sectorsize == sizeof(struct nandfs_fsdata))
continue;
else {
- sb += (sizeof(struct nandfs_fsdata) /
- sizeof(struct nandfs_super_block));
- n -= (sizeof(struct nandfs_fsdata) /
+ s += (sizeof(struct nandfs_fsdata) /
sizeof(struct nandfs_super_block));
}
}
- for (j = 0; j < n; j++) {
+ for (j = s; j < n; j++) {
if (!nandfs_check_superblock_crc(fs->nf_fsdata, &sb[j]))
continue;
- NANDFS_DEBUG("magic %x wtime %jd\n", sb->s_magic,
- sb->s_wtime);
- if (sb[j].s_wtime > fs->nf_sb->s_wtime)
+ NANDFS_DEBUG("magic %x wtime %jd, lastcp 0x%jx\n",
+ sb[j].s_magic, sb[j].s_wtime, sb[j].s_last_cno);
+ if (sb[j].s_last_cno > fs->nf_sb->s_last_cno)
memcpy(fs->nf_sb, &sb[j], sizeof(*fs->nf_sb));
}
}
diff --git a/lib/libstand/nfs.c b/lib/libstand/nfs.c
index e49999d..a7a7ccb 100644
--- a/lib/libstand/nfs.c
+++ b/lib/libstand/nfs.c
@@ -181,6 +181,7 @@ struct nfs_iodesc {
uint32_t fhsize;
u_char fh[NFS_V3MAXFHSIZE];
struct nfsv3_fattrs fa; /* all in network order */
+ uint64_t cookie;
};
#endif /* OLD_NFSV2 */
@@ -486,6 +487,9 @@ nfs_open(const char *upath, struct open_file *f)
desc->destip = rootip;
if ((error = nfs_getrootfh(desc, rootpath, nfs_root_node.fh)))
return (error);
+ nfs_root_node.fa.fa_type = htonl(NFDIR);
+ nfs_root_node.fa.fa_mode = htonl(0755);
+ nfs_root_node.fa.fa_nlink = htonl(2);
nfs_root_node.iodesc = desc;
fh = &nfs_root_node.fh[0];
@@ -498,14 +502,15 @@ nfs_open(const char *upath, struct open_file *f)
setenv("boot.nfsroot.path", rootpath, 1);
setenv("boot.nfsroot.nfshandle", buf, 1);
-#ifndef NFS_NOSYMLINK
- /* Fake up attributes for the root dir. */
- fa = &nfs_root_node.fa;
- fa->fa_type = htonl(NFDIR);
- fa->fa_mode = htonl(0755);
- fa->fa_nlink = htonl(2);
+ /* Allocate file system specific data structure */
+ currfd = malloc(sizeof(*newfd));
+ if (currfd == NULL) {
+ error = ENOMEM;
+ goto out;
+ }
- currfd = &nfs_root_node;
+#ifndef NFS_NOSYMLINK
+ bcopy(&nfs_root_node, currfd, sizeof(*currfd));
newfd = 0;
cp = path = strdup(upath);
@@ -533,7 +538,6 @@ nfs_open(const char *upath, struct open_file *f)
/* allocate file system specific data structure */
newfd = malloc(sizeof(*newfd));
newfd->iodesc = currfd->iodesc;
- newfd->off = 0;
/*
* Get next component of path name.
@@ -585,11 +589,8 @@ nfs_open(const char *upath, struct open_file *f)
* If relative pathname, restart at parent directory.
*/
cp = namebuf;
- if (*cp == '/') {
- if (currfd != &nfs_root_node)
- free(currfd);
- currfd = &nfs_root_node;
- }
+ if (*cp == '/')
+ bcopy(&nfs_root_node, currfd, sizeof(*currfd));
free(newfd);
newfd = 0;
@@ -597,8 +598,7 @@ nfs_open(const char *upath, struct open_file *f)
continue;
}
- if (currfd != &nfs_root_node)
- free(currfd);
+ free(currfd);
currfd = newfd;
newfd = 0;
}
@@ -606,19 +606,15 @@ nfs_open(const char *upath, struct open_file *f)
error = 0;
out:
- if (newfd)
- free(newfd);
- if (path)
- free(path);
+ free(newfd);
+ free(path);
#else
- /* allocate file system specific data structure */
- currfd = malloc(sizeof(*currfd));
currfd->iodesc = desc;
- currfd->off = 0;
error = nfs_lookupfh(&nfs_root_node, upath, currfd);
#endif
if (!error) {
+ currfd->off = 0;
f->f_fsdata = (void *)currfd;
return (0);
}
@@ -628,10 +624,7 @@ out:
printf("nfs_open: %s lookupfh failed: %s\n",
path, strerror(error));
#endif
-#ifndef NFS_NOSYMLINK
- if (currfd != &nfs_root_node)
-#endif
- free(currfd);
+ free(currfd);
return (error);
}
@@ -646,7 +639,7 @@ nfs_close(struct open_file *f)
printf("nfs_close: fp=0x%lx\n", (u_long)fp);
#endif
- if (fp != &nfs_root_node && fp)
+ if (fp)
free(fp);
f->f_fsdata = (void *)0;
@@ -761,6 +754,7 @@ nfs_readdir(struct open_file *f, struct dirent *d)
struct nfs_readdir_data *rd;
struct nfs_readdir_off *roff = NULL;
static char *buf;
+ static struct nfs_iodesc *pfp = NULL;
static n_long cookie = 0;
size_t cc;
n_long eof;
@@ -774,13 +768,14 @@ nfs_readdir(struct open_file *f, struct dirent *d)
u_char d[NFS_READDIRSIZE];
} rdata;
- if (cookie == 0) {
+ if (fp != pfp || fp->off != cookie) {
+ pfp = NULL;
refill:
args = &sdata.d;
bzero(args, sizeof(*args));
bcopy(fp->fh, args->fh, NFS_FHSIZE);
- args->cookie = htonl(cookie);
+ args->cookie = htonl(fp->off);
args->count = htonl(NFS_READDIRSIZE);
cc = rpc_call(fp->iodesc, NFS_PROG, NFS_VER2, NFSPROC_READDIR,
@@ -790,6 +785,8 @@ nfs_readdir(struct open_file *f, struct dirent *d)
roff = (struct nfs_readdir_off *)buf;
if (ntohl(roff->cookie) != 0)
return EIO;
+ pfp = fp;
+ cookie = fp->off;
}
roff = (struct nfs_readdir_off *)buf;
@@ -810,7 +807,7 @@ nfs_readdir(struct open_file *f, struct dirent *d)
buf += (sizeof(struct nfs_readdir_data) + roundup(htonl(rd->len),4));
roff = (struct nfs_readdir_off *)buf;
- cookie = ntohl(roff->cookie);
+ fp->off = cookie = ntohl(roff->cookie);
return 0;
}
#else /* !OLD_NFSV2 */
@@ -1133,6 +1130,9 @@ nfs_open(const char *upath, struct open_file *f)
if ((error = nfs_getrootfh(desc, rootpath, &nfs_root_node.fhsize,
nfs_root_node.fh)))
return (error);
+ nfs_root_node.fa.fa_type = htonl(NFDIR);
+ nfs_root_node.fa.fa_mode = htonl(0755);
+ nfs_root_node.fa.fa_nlink = htonl(2);
nfs_root_node.iodesc = desc;
fh = &nfs_root_node.fh[0];
@@ -1147,14 +1147,14 @@ nfs_open(const char *upath, struct open_file *f)
sprintf(buf, "%d", nfs_root_node.fhsize);
setenv("boot.nfsroot.nfshandlelen", buf, 1);
+ /* Allocate file system specific data structure */
+ currfd = malloc(sizeof(*newfd));
+ if (currfd == NULL) {
+ error = ENOMEM;
+ goto out;
+ }
#ifndef NFS_NOSYMLINK
- /* Fake up attributes for the root dir. */
- fa = &nfs_root_node.fa;
- fa->fa_type = htonl(NFDIR);
- fa->fa_mode = htonl(0755);
- fa->fa_nlink = htonl(2);
-
- currfd = &nfs_root_node;
+ bcopy(&nfs_root_node, currfd, sizeof(*currfd));
newfd = 0;
cp = path = strdup(upath);
@@ -1186,7 +1186,6 @@ nfs_open(const char *upath, struct open_file *f)
goto out;
}
newfd->iodesc = currfd->iodesc;
- newfd->off = 0;
/*
* Get next component of path name.
@@ -1238,11 +1237,8 @@ nfs_open(const char *upath, struct open_file *f)
* If relative pathname, restart at parent directory.
*/
cp = namebuf;
- if (*cp == '/') {
- if (currfd != &nfs_root_node)
- free(currfd);
- currfd = &nfs_root_node;
- }
+ if (*cp == '/')
+ bcopy(&nfs_root_node, currfd, sizeof(*currfd));
free(newfd);
newfd = 0;
@@ -1250,8 +1246,7 @@ nfs_open(const char *upath, struct open_file *f)
continue;
}
- if (currfd != &nfs_root_node)
- free(currfd);
+ free(currfd);
currfd = newfd;
newfd = 0;
}
@@ -1262,17 +1257,13 @@ out:
free(newfd);
free(path);
#else
- /* allocate file system specific data structure */
- currfd = malloc(sizeof(*currfd));
- if (currfd != NULL) {
- currfd->iodesc = desc;
- currfd->off = 0;
+ currfd->iodesc = desc;
- error = nfs_lookupfh(&nfs_root_node, upath, currfd);
- } else
- error = ENOMEM;
+ error = nfs_lookupfh(&nfs_root_node, upath, currfd);
#endif
if (!error) {
+ currfd->off = 0;
+ currfd->cookie = 0;
f->f_fsdata = (void *)currfd;
return (0);
}
@@ -1282,10 +1273,7 @@ out:
printf("nfs_open: %s lookupfh failed: %s\n",
path, strerror(error));
#endif
-#ifndef NFS_NOSYMLINK
- if (currfd != &nfs_root_node)
-#endif
- free(currfd);
+ free(currfd);
return (error);
}
@@ -1300,7 +1288,7 @@ nfs_close(struct open_file *f)
printf("nfs_close: fp=0x%lx\n", (u_long)fp);
#endif
- if (fp != &nfs_root_node && fp)
+ if (fp)
free(fp);
f->f_fsdata = (void *)0;
@@ -1414,11 +1402,9 @@ nfs_readdir(struct open_file *f, struct dirent *d)
struct nfsv3_readdir_repl *repl;
struct nfsv3_readdir_entry *rent;
static char *buf;
- static uint32_t cookie0 = 0;
- static uint32_t cookie1 = 0;
+ static struct nfs_iodesc *pfp = NULL;
+ static uint64_t cookie = 0;
size_t cc;
- static uint32_t cookieverf0 = 0;
- static uint32_t cookieverf1 = 0;
int pos;
struct args {
@@ -1434,7 +1420,8 @@ nfs_readdir(struct open_file *f, struct dirent *d)
u_char d[NFS_READDIRSIZE];
} rdata;
- if (cookie0 == 0 && cookie1 == 0) {
+ if (fp != pfp || fp->off != cookie) {
+ pfp = NULL;
refill:
args = &sdata.d;
bzero(args, sizeof(*args));
@@ -1442,10 +1429,10 @@ nfs_readdir(struct open_file *f, struct dirent *d)
args->fhsize = htonl(fp->fhsize);
bcopy(fp->fh, args->fhpluscookie, fp->fhsize);
pos = roundup(fp->fhsize, sizeof(uint32_t)) / sizeof(uint32_t);
- args->fhpluscookie[pos++] = cookie0;
- args->fhpluscookie[pos++] = cookie1;
- args->fhpluscookie[pos++] = cookieverf0;
- args->fhpluscookie[pos++] = cookieverf1;
+ args->fhpluscookie[pos++] = htonl(fp->off >> 32);
+ args->fhpluscookie[pos++] = htonl(fp->off);
+ args->fhpluscookie[pos++] = htonl(fp->cookie >> 32);
+ args->fhpluscookie[pos++] = htonl(fp->cookie);
args->fhpluscookie[pos] = htonl(NFS_READDIRSIZE);
cc = rpc_call(fp->iodesc, NFS_PROG, NFS_VER3, NFSPROCV3_READDIR,
@@ -1456,8 +1443,10 @@ nfs_readdir(struct open_file *f, struct dirent *d)
repl = (struct nfsv3_readdir_repl *)buf;
if (repl->errno != 0)
return (ntohl(repl->errno));
- cookieverf0 = repl->cookiev0;
- cookieverf1 = repl->cookiev1;
+ pfp = fp;
+ cookie = fp->off;
+ fp->cookie = ((uint64_t)ntohl(repl->cookiev0) << 32) |
+ ntohl(repl->cookiev1);
buf += sizeof (struct nfsv3_readdir_repl);
}
rent = (struct nfsv3_readdir_entry *)buf;
@@ -1465,10 +1454,7 @@ nfs_readdir(struct open_file *f, struct dirent *d)
if (rent->follows == 0) {
/* fid0 is actually eof */
if (rent->fid0 != 0) {
- cookie0 = 0;
- cookie1 = 0;
- cookieverf0 = 0;
- cookieverf1 = 0;
+ cookie = 0;
return (ENOENT);
}
goto refill;
@@ -1479,8 +1465,8 @@ nfs_readdir(struct open_file *f, struct dirent *d)
d->d_name[d->d_namlen] = '\0';
pos = roundup(d->d_namlen, sizeof(uint32_t)) / sizeof(uint32_t);
- cookie0 = rent->nameplus[pos++];
- cookie1 = rent->nameplus[pos++];
+ fp->off = cookie = ((uint64_t)ntohl(rent->nameplus[pos++]) << 32) |
+ ntohl(rent->nameplus[pos++]);
buf = (u_char *)&rent->nameplus[pos];
return (0);
}
diff --git a/lib/libstdbuf/Makefile b/lib/libstdbuf/Makefile
index cf65e4f..ea233a8 100644
--- a/lib/libstdbuf/Makefile
+++ b/lib/libstdbuf/Makefile
@@ -7,6 +7,4 @@ SRCS= stdbuf.c
SHLIB_MAJOR= 1
MAN= libstdbuf.3
-WARNS?= 6
-
.include <bsd.lib.mk>
diff --git a/lib/libthr/arch/arm/include/pthread_md.h b/lib/libthr/arch/arm/include/pthread_md.h
index 83ddf7f..3c3dd6d 100644
--- a/lib/libthr/arch/arm/include/pthread_md.h
+++ b/lib/libthr/arch/arm/include/pthread_md.h
@@ -57,7 +57,11 @@ void _tcb_dtor(struct tcb *);
static __inline void
_tcb_set(struct tcb *tcb)
{
- *((struct tcb **)ARM_TP_ADDRESS) = tcb;
+#ifdef ARM_TP_ADDRESS
+ *((struct tcb **)ARM_TP_ADDRESS) = tcb; /* avoids a system call */
+#else
+ sysarch(ARM_SET_TP, tcb);
+#endif
}
/*
@@ -66,7 +70,15 @@ _tcb_set(struct tcb *tcb)
static __inline struct tcb *
_tcb_get(void)
{
+#ifdef ARM_TP_ADDRESS
return (*((struct tcb **)ARM_TP_ADDRESS));
+#else
+ struct tcb *tcb;
+
+ __asm __volatile("mrc p15, 0, %0, c13, c0, 3" \
+ : "=r" (tcb));
+ return (tcb);
+#endif
}
extern struct pthread *_thr_initial;
diff --git a/lib/libthr/thread/thr_cond.c b/lib/libthr/thread/thr_cond.c
index a834711..6af15db 100644
--- a/lib/libthr/thread/thr_cond.c
+++ b/lib/libthr/thread/thr_cond.c
@@ -217,6 +217,7 @@ cond_wait_user(struct pthread_cond *cvp, struct pthread_mutex *mp,
struct sleepqueue *sq;
int recurse;
int error;
+ int defered;
if (curthread->wchan != NULL)
PANIC("thread was already on queue.");
@@ -230,13 +231,24 @@ cond_wait_user(struct pthread_cond *cvp, struct pthread_mutex *mp,
* us to check it without locking in pthread_cond_signal().
*/
cvp->__has_user_waiters = 1;
- curthread->will_sleep = 1;
- (void)_mutex_cv_unlock(mp, &recurse);
+ defered = 0;
+ (void)_mutex_cv_unlock(mp, &recurse, &defered);
curthread->mutex_obj = mp;
_sleepq_add(cvp, curthread);
for(;;) {
_thr_clear_wake(curthread);
_sleepq_unlock(cvp);
+ if (defered) {
+ defered = 0;
+ if ((mp->m_lock.m_owner & UMUTEX_CONTESTED) == 0)
+ (void)_umtx_op_err(&mp->m_lock, UMTX_OP_MUTEX_WAKE2,
+ mp->m_lock.m_flags, 0, 0);
+ }
+ if (curthread->nwaiter_defer > 0) {
+ _thr_wake_all(curthread->defer_waiters,
+ curthread->nwaiter_defer);
+ curthread->nwaiter_defer = 0;
+ }
if (cancel) {
_thr_cancel_enter2(curthread, 0);
diff --git a/lib/libthr/thread/thr_fork.c b/lib/libthr/thread/thr_fork.c
index a1399bf..c26541e 100644
--- a/lib/libthr/thread/thr_fork.c
+++ b/lib/libthr/thread/thr_fork.c
@@ -200,9 +200,6 @@ _fork(void)
_rtld_atfork_post(rtld_locks);
_thr_setthreaded(0);
- /* reinitialize libc spinlocks. */
- _thr_spinlock_init();
-
/* reinitalize library. */
_libpthread_init(curthread);
diff --git a/lib/libthr/thread/thr_getcpuclockid.c b/lib/libthr/thread/thr_getcpuclockid.c
index 68f88d5..b4ec666 100644
--- a/lib/libthr/thread/thr_getcpuclockid.c
+++ b/lib/libthr/thread/thr_getcpuclockid.c
@@ -39,9 +39,11 @@ __weak_reference(_pthread_getcpuclockid, pthread_getcpuclockid);
int
_pthread_getcpuclockid(pthread_t pthread, clockid_t *clock_id)
{
+
if (pthread == NULL)
return (EINVAL);
- *clock_id = CLOCK_THREAD_CPUTIME_ID;
+ if (clock_getcpuclockid2(TID(pthread), CPUCLOCK_WHICH_TID, clock_id))
+ return (errno);
return (0);
}
diff --git a/lib/libthr/thread/thr_getschedparam.c b/lib/libthr/thread/thr_getschedparam.c
index b36d724..ff6c3ab 100644
--- a/lib/libthr/thread/thr_getschedparam.c
+++ b/lib/libthr/thread/thr_getschedparam.c
@@ -48,30 +48,21 @@ _pthread_getschedparam(pthread_t pthread, int *policy,
struct sched_param *param)
{
struct pthread *curthread = _get_curthread();
- int ret;
+ int ret = 0;
if (policy == NULL || param == NULL)
return (EINVAL);
- if (pthread == curthread) {
- /*
- * Avoid searching the thread list when it is the current
- * thread.
- */
+ /*
+ * Avoid searching the thread list when it is the current
+ * thread.
+ */
+ if (pthread == curthread)
THR_LOCK(curthread);
- *policy = curthread->attr.sched_policy;
- param->sched_priority = curthread->attr.prio;
- THR_UNLOCK(curthread);
- ret = 0;
- }
- /* Find the thread in the list of active threads. */
- else if ((ret = _thr_ref_add(curthread, pthread, /*include dead*/0))
- == 0) {
- THR_THREAD_LOCK(curthread, pthread);
- *policy = pthread->attr.sched_policy;
- param->sched_priority = pthread->attr.prio;
- THR_THREAD_UNLOCK(curthread, pthread);
- _thr_ref_delete(curthread, pthread);
- }
+ else if ((ret = _thr_find_thread(curthread, pthread, /*include dead*/0)))
+ return (ret);
+ *policy = pthread->attr.sched_policy;
+ param->sched_priority = pthread->attr.prio;
+ THR_THREAD_UNLOCK(curthread, pthread);
return (ret);
}
diff --git a/lib/libthr/thread/thr_info.c b/lib/libthr/thread/thr_info.c
index 2da6da2..350c848 100644
--- a/lib/libthr/thread/thr_info.c
+++ b/lib/libthr/thread/thr_info.c
@@ -51,16 +51,12 @@ _pthread_set_name_np(pthread_t thread, const char *name)
if (thr_set_name(thread->tid, name))
ret = errno;
} else {
- if (_thr_ref_add(curthread, thread, 0) == 0) {
- THR_THREAD_LOCK(curthread, thread);
+ if ((ret=_thr_find_thread(curthread, thread, 0)) == 0) {
if (thread->state != PS_DEAD) {
if (thr_set_name(thread->tid, name))
ret = errno;
}
THR_THREAD_UNLOCK(curthread, thread);
- _thr_ref_delete(curthread, thread);
- } else {
- ret = ESRCH;
}
}
#if 0
diff --git a/lib/libthr/thread/thr_init.c b/lib/libthr/thread/thr_init.c
index e1e304a..c29e8c3 100644
--- a/lib/libthr/thread/thr_init.c
+++ b/lib/libthr/thread/thr_init.c
@@ -120,6 +120,10 @@ struct umutex _rwlock_static_lock = DEFAULT_UMUTEX;
struct umutex _keytable_lock = DEFAULT_UMUTEX;
struct urwlock _thr_list_lock = DEFAULT_URWLOCK;
struct umutex _thr_event_lock = DEFAULT_UMUTEX;
+struct umutex _suspend_all_lock = DEFAULT_UMUTEX;
+struct pthread *_single_thread;
+int _suspend_all_cycle;
+int _suspend_all_waiters;
int __pthread_cond_wait(pthread_cond_t *, pthread_mutex_t *);
int __pthread_mutex_lock(pthread_mutex_t *);
@@ -441,11 +445,14 @@ init_private(void)
_thr_umutex_init(&_keytable_lock);
_thr_urwlock_init(&_thr_atfork_lock);
_thr_umutex_init(&_thr_event_lock);
+ _thr_umutex_init(&_suspend_all_lock);
_thr_once_init();
_thr_spinlock_init();
_thr_list_init();
_thr_wake_addr_init();
_sleepq_init();
+ _single_thread = NULL;
+ _suspend_all_waiters = 0;
/*
* Avoid reinitializing some things if they don't need to be,
diff --git a/lib/libthr/thread/thr_kern.c b/lib/libthr/thread/thr_kern.c
index 48f7c65..1e7cb51 100644
--- a/lib/libthr/thread/thr_kern.c
+++ b/lib/libthr/thread/thr_kern.c
@@ -199,13 +199,6 @@ _thr_sleep(struct pthread *curthread, int clockid,
const struct timespec *abstime)
{
- curthread->will_sleep = 0;
- if (curthread->nwaiter_defer > 0) {
- _thr_wake_all(curthread->defer_waiters,
- curthread->nwaiter_defer);
- curthread->nwaiter_defer = 0;
- }
-
if (curthread->wake_addr->value != 0)
return (0);
diff --git a/lib/libthr/thread/thr_mutex.c b/lib/libthr/thread/thr_mutex.c
index 91b47ec..61ff077 100644
--- a/lib/libthr/thread/thr_mutex.c
+++ b/lib/libthr/thread/thr_mutex.c
@@ -92,7 +92,7 @@ int __pthread_mutex_setyieldloops_np(pthread_mutex_t *mutex, int count);
static int mutex_self_trylock(pthread_mutex_t);
static int mutex_self_lock(pthread_mutex_t,
const struct timespec *abstime);
-static int mutex_unlock_common(struct pthread_mutex *, int);
+static int mutex_unlock_common(struct pthread_mutex *, int, int *);
static int mutex_lock_sleep(struct pthread *, pthread_mutex_t,
const struct timespec *);
@@ -461,7 +461,7 @@ _pthread_mutex_unlock(pthread_mutex_t *mutex)
struct pthread_mutex *mp;
mp = *mutex;
- return (mutex_unlock_common(mp, 0));
+ return (mutex_unlock_common(mp, 0, NULL));
}
int
@@ -476,7 +476,7 @@ _mutex_cv_lock(struct pthread_mutex *m, int count)
}
int
-_mutex_cv_unlock(struct pthread_mutex *m, int *count)
+_mutex_cv_unlock(struct pthread_mutex *m, int *count, int *defer)
{
/*
@@ -484,7 +484,7 @@ _mutex_cv_unlock(struct pthread_mutex *m, int *count)
*/
*count = m->m_count;
m->m_count = 0;
- (void)mutex_unlock_common(m, 1);
+ (void)mutex_unlock_common(m, 1, defer);
return (0);
}
@@ -629,7 +629,7 @@ mutex_self_lock(struct pthread_mutex *m, const struct timespec *abstime)
}
static int
-mutex_unlock_common(struct pthread_mutex *m, int cv)
+mutex_unlock_common(struct pthread_mutex *m, int cv, int *mtx_defer)
{
struct pthread *curthread = _get_curthread();
uint32_t id;
@@ -657,12 +657,12 @@ mutex_unlock_common(struct pthread_mutex *m, int cv)
defered = 1;
m->m_flags &= ~PMUTEX_FLAG_DEFERED;
} else
- defered = 0;
+ defered = 0;
DEQUEUE_MUTEX(curthread, m);
- _thr_umutex_unlock(&m->m_lock, id);
+ _thr_umutex_unlock2(&m->m_lock, id, mtx_defer);
- if (curthread->will_sleep == 0 && defered) {
+ if (mtx_defer == NULL && defered) {
_thr_wake_all(curthread->defer_waiters,
curthread->nwaiter_defer);
curthread->nwaiter_defer = 0;
diff --git a/lib/libthr/thread/thr_private.h b/lib/libthr/thread/thr_private.h
index 5224c7c..fb76290 100644
--- a/lib/libthr/thread/thr_private.h
+++ b/lib/libthr/thread/thr_private.h
@@ -721,16 +721,20 @@ extern struct umutex _rwlock_static_lock __hidden;
extern struct umutex _keytable_lock __hidden;
extern struct urwlock _thr_list_lock __hidden;
extern struct umutex _thr_event_lock __hidden;
+extern struct umutex _suspend_all_lock __hidden;
+extern int _suspend_all_waiters __hidden;
+extern int _suspend_all_cycle __hidden;
+extern struct pthread *_single_thread __hidden;
/*
* Function prototype definitions.
*/
__BEGIN_DECLS
int _thr_setthreaded(int) __hidden;
-int _mutex_cv_lock(struct pthread_mutex *, int count) __hidden;
-int _mutex_cv_unlock(struct pthread_mutex *, int *count) __hidden;
-int _mutex_cv_attach(struct pthread_mutex *, int count) __hidden;
-int _mutex_cv_detach(struct pthread_mutex *, int *count) __hidden;
+int _mutex_cv_lock(struct pthread_mutex *, int) __hidden;
+int _mutex_cv_unlock(struct pthread_mutex *, int *, int *) __hidden;
+int _mutex_cv_attach(struct pthread_mutex *, int) __hidden;
+int _mutex_cv_detach(struct pthread_mutex *, int *) __hidden;
int _mutex_owned(struct pthread *, const struct pthread_mutex *) __hidden;
int _mutex_reinit(pthread_mutex_t *) __hidden;
void _mutex_fork(struct pthread *curthread) __hidden;
@@ -777,6 +781,8 @@ int _thr_setscheduler(lwpid_t, int, const struct sched_param *) __hidden;
void _thr_signal_prefork(void) __hidden;
void _thr_signal_postfork(void) __hidden;
void _thr_signal_postfork_child(void) __hidden;
+void _thr_suspend_all_lock(struct pthread *) __hidden;
+void _thr_suspend_all_unlock(struct pthread *) __hidden;
void _thr_try_gc(struct pthread *, struct pthread *) __hidden;
int _rtp_to_schedparam(const struct rtprio *rtp, int *policy,
struct sched_param *param) __hidden;
diff --git a/lib/libthr/thread/thr_resume_np.c b/lib/libthr/thread/thr_resume_np.c
index a3066bc..53377da 100644
--- a/lib/libthr/thread/thr_resume_np.c
+++ b/lib/libthr/thread/thr_resume_np.c
@@ -63,7 +63,11 @@ _pthread_resume_all_np(void)
{
struct pthread *curthread = _get_curthread();
struct pthread *thread;
+ int old_nocancel;
+ old_nocancel = curthread->no_cancel;
+ curthread->no_cancel = 1;
+ _thr_suspend_all_lock(curthread);
/* Take the thread list lock: */
THREAD_LIST_RDLOCK(curthread);
@@ -77,6 +81,9 @@ _pthread_resume_all_np(void)
/* Release the thread list lock: */
THREAD_LIST_UNLOCK(curthread);
+ _thr_suspend_all_unlock(curthread);
+ curthread->no_cancel = old_nocancel;
+ _thr_testcancel(curthread);
}
static void
diff --git a/lib/libthr/thread/thr_setprio.c b/lib/libthr/thread/thr_setprio.c
index b1b2352..4b7d2c0 100644
--- a/lib/libthr/thread/thr_setprio.c
+++ b/lib/libthr/thread/thr_setprio.c
@@ -45,38 +45,22 @@ _pthread_setprio(pthread_t pthread, int prio)
int ret;
param.sched_priority = prio;
- if (pthread == curthread) {
+ if (pthread == curthread)
THR_LOCK(curthread);
- if (curthread->attr.sched_policy == SCHED_OTHER ||
- curthread->attr.prio == prio) {
- curthread->attr.prio = prio;
- ret = 0;
- } else {
- ret = _thr_setscheduler(curthread->tid,
- curthread->attr.sched_policy, &param);
- if (ret == -1)
- ret = errno;
- else
- curthread->attr.prio = prio;
- }
- THR_UNLOCK(curthread);
- } else if ((ret = _thr_ref_add(curthread, pthread, /*include dead*/0))
- == 0) {
- THR_THREAD_LOCK(curthread, pthread);
- if (pthread->attr.sched_policy == SCHED_OTHER ||
- pthread->attr.prio == prio) {
+ else if ((ret = _thr_find_thread(curthread, pthread, /*include dead*/0)))
+ return (ret);
+ if (pthread->attr.sched_policy == SCHED_OTHER ||
+ pthread->attr.prio == prio) {
+ pthread->attr.prio = prio;
+ ret = 0;
+ } else {
+ ret = _thr_setscheduler(pthread->tid,
+ pthread->attr.sched_policy, &param);
+ if (ret == -1)
+ ret = errno;
+ else
pthread->attr.prio = prio;
- ret = 0;
- } else {
- ret = _thr_setscheduler(pthread->tid,
- curthread->attr.sched_policy, &param);
- if (ret == -1)
- ret = errno;
- else
- pthread->attr.prio = prio;
- }
- THR_THREAD_UNLOCK(curthread, pthread);
- _thr_ref_delete(curthread, pthread);
}
+ THR_THREAD_UNLOCK(curthread, pthread);
return (ret);
}
diff --git a/lib/libthr/thread/thr_setschedparam.c b/lib/libthr/thread/thr_setschedparam.c
index 59d62dc..6e98fb4 100644
--- a/lib/libthr/thread/thr_setschedparam.c
+++ b/lib/libthr/thread/thr_setschedparam.c
@@ -53,42 +53,25 @@ _pthread_setschedparam(pthread_t pthread, int policy,
struct pthread *curthread = _get_curthread();
int ret;
- if (pthread == curthread) {
+ if (pthread == curthread)
THR_LOCK(curthread);
- if (curthread->attr.sched_policy == policy &&
- (policy == SCHED_OTHER ||
- curthread->attr.prio == param->sched_priority)) {
- pthread->attr.prio = param->sched_priority;
- THR_UNLOCK(curthread);
- return (0);
- }
- ret = _thr_setscheduler(curthread->tid, policy, param);
- if (ret == -1)
- ret = errno;
- else {
- curthread->attr.sched_policy = policy;
- curthread->attr.prio = param->sched_priority;
- }
- THR_UNLOCK(curthread);
- } else if ((ret = _thr_ref_add(curthread, pthread, /*include dead*/0))
- == 0) {
- THR_THREAD_LOCK(curthread, pthread);
- if (pthread->attr.sched_policy == policy &&
- (policy == SCHED_OTHER ||
- pthread->attr.prio == param->sched_priority)) {
- pthread->attr.prio = param->sched_priority;
- THR_THREAD_UNLOCK(curthread, pthread);
- return (0);
- }
- ret = _thr_setscheduler(pthread->tid, policy, param);
- if (ret == -1)
- ret = errno;
- else {
- pthread->attr.sched_policy = policy;
- pthread->attr.prio = param->sched_priority;
- }
+ else if ((ret = _thr_find_thread(curthread, pthread,
+ /*include dead*/0)) != 0)
+ return (ret);
+ if (pthread->attr.sched_policy == policy &&
+ (policy == SCHED_OTHER ||
+ pthread->attr.prio == param->sched_priority)) {
+ pthread->attr.prio = param->sched_priority;
THR_THREAD_UNLOCK(curthread, pthread);
- _thr_ref_delete(curthread, pthread);
+ return (0);
}
+ ret = _thr_setscheduler(pthread->tid, policy, param);
+ if (ret == -1)
+ ret = errno;
+ else {
+ pthread->attr.sched_policy = policy;
+ pthread->attr.prio = param->sched_priority;
+ }
+ THR_THREAD_UNLOCK(curthread, pthread);
return (ret);
}
diff --git a/lib/libthr/thread/thr_sig.c b/lib/libthr/thread/thr_sig.c
index 3dee8b7..d2be994 100644
--- a/lib/libthr/thread/thr_sig.c
+++ b/lib/libthr/thread/thr_sig.c
@@ -356,7 +356,8 @@ check_suspend(struct pthread *curthread)
(THR_FLAGS_NEED_SUSPEND | THR_FLAGS_SUSPENDED))
!= THR_FLAGS_NEED_SUSPEND))
return;
-
+ if (curthread == _single_thread)
+ return;
if (curthread->force_exit)
return;
diff --git a/lib/libthr/thread/thr_suspend_np.c b/lib/libthr/thread/thr_suspend_np.c
index d5868e8..284619d 100644
--- a/lib/libthr/thread/thr_suspend_np.c
+++ b/lib/libthr/thread/thr_suspend_np.c
@@ -70,14 +70,48 @@ _pthread_suspend_np(pthread_t thread)
}
void
+_thr_suspend_all_lock(struct pthread *curthread)
+{
+ int old;
+
+ THR_LOCK_ACQUIRE(curthread, &_suspend_all_lock);
+ while (_single_thread != NULL) {
+ old = _suspend_all_cycle;
+ _suspend_all_waiters++;
+ THR_LOCK_RELEASE(curthread, &_suspend_all_lock);
+ _thr_umtx_wait_uint(&_suspend_all_cycle, old, NULL, 0);
+ THR_LOCK_ACQUIRE(curthread, &_suspend_all_lock);
+ _suspend_all_waiters--;
+ }
+ _single_thread = curthread;
+ THR_LOCK_RELEASE(curthread, &_suspend_all_lock);
+}
+
+void
+_thr_suspend_all_unlock(struct pthread *curthread)
+{
+
+ THR_LOCK_ACQUIRE(curthread, &_suspend_all_lock);
+ _single_thread = NULL;
+ if (_suspend_all_waiters != 0) {
+ _suspend_all_cycle++;
+ _thr_umtx_wake(&_suspend_all_cycle, INT_MAX, 0);
+ }
+ THR_LOCK_RELEASE(curthread, &_suspend_all_lock);
+}
+
+void
_pthread_suspend_all_np(void)
{
struct pthread *curthread = _get_curthread();
struct pthread *thread;
+ int old_nocancel;
int ret;
+ old_nocancel = curthread->no_cancel;
+ curthread->no_cancel = 1;
+ _thr_suspend_all_lock(curthread);
THREAD_LIST_RDLOCK(curthread);
-
TAILQ_FOREACH(thread, &_thread_list, tle) {
if (thread != curthread) {
THR_THREAD_LOCK(curthread, thread);
@@ -115,19 +149,24 @@ restart:
THR_THREAD_UNLOCK(curthread, thread);
}
}
-
THREAD_LIST_UNLOCK(curthread);
+ _thr_suspend_all_unlock(curthread);
+ curthread->no_cancel = old_nocancel;
+ _thr_testcancel(curthread);
}
static int
suspend_common(struct pthread *curthread, struct pthread *thread,
int waitok)
{
- long tmp;
+ uint32_t tmp;
while (thread->state != PS_DEAD &&
!(thread->flags & THR_FLAGS_SUSPENDED)) {
thread->flags |= THR_FLAGS_NEED_SUSPEND;
+ /* Thread is in creation. */
+ if (thread->tid == TID_TERMINATED)
+ return (1);
tmp = thread->cycle;
_thr_send_sig(thread, SIGCANCEL);
THR_THREAD_UNLOCK(curthread, thread);
diff --git a/lib/libthr/thread/thr_umtx.h b/lib/libthr/thread/thr_umtx.h
index d74cc81..f3d95f1 100644
--- a/lib/libthr/thread/thr_umtx.h
+++ b/lib/libthr/thread/thr_umtx.h
@@ -120,7 +120,7 @@ _thr_umutex_timedlock(struct umutex *mtx, uint32_t id,
}
static inline int
-_thr_umutex_unlock(struct umutex *mtx, uint32_t id)
+_thr_umutex_unlock2(struct umutex *mtx, uint32_t id, int *defer)
{
uint32_t flags = mtx->m_flags;
@@ -132,8 +132,12 @@ _thr_umutex_unlock(struct umutex *mtx, uint32_t id)
return (EPERM);
} while (__predict_false(!atomic_cmpset_rel_32(&mtx->m_owner,
owner, UMUTEX_UNOWNED)));
- if ((owner & UMUTEX_CONTESTED))
- (void)_umtx_op_err(mtx, UMTX_OP_MUTEX_WAKE2, flags, 0, 0);
+ if ((owner & UMUTEX_CONTESTED)) {
+ if (defer == NULL)
+ (void)_umtx_op_err(mtx, UMTX_OP_MUTEX_WAKE2, flags, 0, 0);
+ else
+ *defer = 1;
+ }
return (0);
}
if (atomic_cmpset_rel_32(&mtx->m_owner, id, UMUTEX_UNOWNED))
@@ -142,6 +146,12 @@ _thr_umutex_unlock(struct umutex *mtx, uint32_t id)
}
static inline int
+_thr_umutex_unlock(struct umutex *mtx, uint32_t id)
+{
+ return _thr_umutex_unlock2(mtx, id, NULL);
+}
+
+static inline int
_thr_rwlock_tryrdlock(struct urwlock *rwlock, int flags)
{
int32_t state;
diff --git a/lib/libthread_db/libpthread_db.c b/lib/libthread_db/libpthread_db.c
index 31ea15d..e190e56 100644
--- a/lib/libthread_db/libpthread_db.c
+++ b/lib/libthread_db/libpthread_db.c
@@ -1107,7 +1107,7 @@ pt_thr_tls_get_addr(const td_thrhandle_t *th, psaddr_t _linkmap, size_t offset,
return (TD_OK);
}
-struct ta_ops libpthread_db_ops = {
+static struct ta_ops libpthread_db_ops = {
.to_init = pt_init,
.to_ta_clear_event = pt_ta_clear_event,
.to_ta_delete = pt_ta_delete,
diff --git a/lib/libthread_db/libthr_db.c b/lib/libthread_db/libthr_db.c
index b24385f..c20394c 100644
--- a/lib/libthread_db/libthr_db.c
+++ b/lib/libthread_db/libthr_db.c
@@ -765,7 +765,7 @@ pt_thr_tls_get_addr(const td_thrhandle_t *th, psaddr_t _linkmap, size_t offset,
return (TD_OK);
}
-struct ta_ops libthr_db_ops = {
+static struct ta_ops libthr_db_ops = {
.to_init = pt_init,
.to_ta_clear_event = pt_ta_clear_event,
.to_ta_delete = pt_ta_delete,
diff --git a/lib/libusb/libusb20.3 b/lib/libusb/libusb20.3
index c9bf902..af80c6c 100644
--- a/lib/libusb/libusb20.3
+++ b/lib/libusb/libusb20.3
@@ -26,7 +26,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd October 14, 2010
+.Dd August 13, 2012
.Dt LIBUSB20 3
.Os
.Sh NAME
@@ -48,6 +48,7 @@ USB access library (libusb -lusb)
.Fn libusb20_tr_close "struct libusb20_transfer *xfer"
.Ft int
.Fn libusb20_tr_open "struct libusb20_transfer *xfer" "uint32_t max_buf_size" "uint32_t max_frame_count" "uint8_t ep_no"
+.Fn libusb20_tr_open_stream "struct libusb20_transfer *xfer" "uint32_t max_buf_size" "uint32_t max_frame_count" "uint8_t ep_no" "uint16_t stream_id"
.Ft struct libusb20_transfer*
.Fn libusb20_tr_get_pointer "struct libusb20_device *pdev" "uint16_t tr_index"
.Ft uint16_t
@@ -284,6 +285,16 @@ Non-zero return values indicate a LIBUSB20_ERROR value.
.
.Pp
.
+.Fn libusb20_tr_open_stream
+is identical to
+.Fn libusb20_tr_open
+except that a stream ID can be specified for BULK endpoints having
+such a feature.
+.Fn libusb20_tr_open
+can be used to open stream ID zero.
+.
+.Pp
+.
.Fn libusb20_tr_get_pointer
will return a pointer to the allocated USB transfer according to the
.Fa pdev
diff --git a/lib/libusb/libusb20.c b/lib/libusb/libusb20.c
index 75af7a1..aa45991 100644
--- a/lib/libusb/libusb20.c
+++ b/lib/libusb/libusb20.c
@@ -155,6 +155,13 @@ int
libusb20_tr_open(struct libusb20_transfer *xfer, uint32_t MaxBufSize,
uint32_t MaxFrameCount, uint8_t ep_no)
{
+ return (libusb20_tr_open_stream(xfer, MaxBufSize, MaxFrameCount, ep_no, 0));
+}
+
+int
+libusb20_tr_open_stream(struct libusb20_transfer *xfer, uint32_t MaxBufSize,
+ uint32_t MaxFrameCount, uint8_t ep_no, uint16_t stream_id)
+{
uint32_t size;
uint8_t pre_scale;
int error;
@@ -188,7 +195,7 @@ libusb20_tr_open(struct libusb20_transfer *xfer, uint32_t MaxBufSize,
memset(xfer->ppBuffer, 0, size);
error = xfer->pdev->methods->tr_open(xfer, MaxBufSize,
- MaxFrameCount, ep_no, pre_scale);
+ MaxFrameCount, ep_no, stream_id, pre_scale);
if (error) {
free(xfer->ppBuffer);
diff --git a/lib/libusb/libusb20.h b/lib/libusb/libusb20.h
index e4359fc..87e0572 100644
--- a/lib/libusb/libusb20.h
+++ b/lib/libusb/libusb20.h
@@ -202,6 +202,7 @@ struct libusb20_quirk {
/* USB transfer operations */
int libusb20_tr_close(struct libusb20_transfer *xfer);
int libusb20_tr_open(struct libusb20_transfer *xfer, uint32_t max_buf_size, uint32_t max_frame_count, uint8_t ep_no);
+int libusb20_tr_open_stream(struct libusb20_transfer *xfer, uint32_t max_buf_size, uint32_t max_frame_count, uint8_t ep_no, uint16_t stream_id);
struct libusb20_transfer *libusb20_tr_get_pointer(struct libusb20_device *pdev, uint16_t tr_index);
uint16_t libusb20_tr_get_time_complete(struct libusb20_transfer *xfer);
uint32_t libusb20_tr_get_actual_frames(struct libusb20_transfer *xfer);
diff --git a/lib/libusb/libusb20_int.h b/lib/libusb/libusb20_int.h
index bef4d02..0251c5f 100644
--- a/lib/libusb/libusb20_int.h
+++ b/lib/libusb/libusb20_int.h
@@ -110,7 +110,7 @@ typedef int (libusb20_set_config_index_t)(struct libusb20_device *pdev, uint8_t
typedef int (libusb20_check_connected_t)(struct libusb20_device *pdev);
/* USB transfer specific */
-typedef int (libusb20_tr_open_t)(struct libusb20_transfer *xfer, uint32_t MaxBufSize, uint32_t MaxFrameCount, uint8_t ep_no, uint8_t pre_scale);
+typedef int (libusb20_tr_open_t)(struct libusb20_transfer *xfer, uint32_t MaxBufSize, uint32_t MaxFrameCount, uint8_t ep_no, uint16_t stream_id, uint8_t pre_scale);
typedef int (libusb20_tr_close_t)(struct libusb20_transfer *xfer);
typedef int (libusb20_tr_clear_stall_sync_t)(struct libusb20_transfer *xfer);
typedef void (libusb20_tr_submit_t)(struct libusb20_transfer *xfer);
diff --git a/lib/libusb/libusb20_ugen20.c b/lib/libusb/libusb20_ugen20.c
index 17c948b..2c67778 100644
--- a/lib/libusb/libusb20_ugen20.c
+++ b/lib/libusb/libusb20_ugen20.c
@@ -741,9 +741,13 @@ ugen20_process(struct libusb20_device *pdev)
static int
ugen20_tr_open(struct libusb20_transfer *xfer, uint32_t MaxBufSize,
- uint32_t MaxFrameCount, uint8_t ep_no, uint8_t pre_scale)
+ uint32_t MaxFrameCount, uint8_t ep_no, uint16_t stream_id,
+ uint8_t pre_scale)
{
- struct usb_fs_open temp;
+ union {
+ struct usb_fs_open fs_open;
+ struct usb_fs_open_stream fs_open_stream;
+ } temp;
struct usb_fs_endpoint *fsep;
if (pre_scale)
@@ -754,20 +758,26 @@ ugen20_tr_open(struct libusb20_transfer *xfer, uint32_t MaxBufSize,
fsep = xfer->pdev->privBeData;
fsep += xfer->trIndex;
- temp.max_bufsize = MaxBufSize;
- temp.max_frames = MaxFrameCount;
- temp.ep_index = xfer->trIndex;
- temp.ep_no = ep_no;
+ temp.fs_open.max_bufsize = MaxBufSize;
+ temp.fs_open.max_frames = MaxFrameCount;
+ temp.fs_open.ep_index = xfer->trIndex;
+ temp.fs_open.ep_no = ep_no;
- if (ioctl(xfer->pdev->file, USB_FS_OPEN, &temp)) {
- return (LIBUSB20_ERROR_INVALID_PARAM);
+ if (stream_id != 0) {
+ temp.fs_open_stream.stream_id = stream_id;
+
+ if (ioctl(xfer->pdev->file, USB_FS_OPEN_STREAM, &temp.fs_open_stream))
+ return (LIBUSB20_ERROR_INVALID_PARAM);
+ } else {
+ if (ioctl(xfer->pdev->file, USB_FS_OPEN, &temp.fs_open))
+ return (LIBUSB20_ERROR_INVALID_PARAM);
}
/* maximums might have changed - update */
- xfer->maxFrames = temp.max_frames;
+ xfer->maxFrames = temp.fs_open.max_frames;
/* "max_bufsize" should be multiple of "max_packet_length" */
- xfer->maxTotalLength = temp.max_bufsize;
- xfer->maxPacketLen = temp.max_packet_length;
+ xfer->maxTotalLength = temp.fs_open.max_bufsize;
+ xfer->maxPacketLen = temp.fs_open.max_packet_length;
/* setup buffer and length lists using zero copy */
fsep->ppBuffer = libusb20_pass_ptr(xfer->ppBuffer);
diff --git a/lib/libusbhid/descr.c b/lib/libusbhid/descr.c
index def90da..0c66342 100644
--- a/lib/libusbhid/descr.c
+++ b/lib/libusbhid/descr.c
@@ -68,7 +68,7 @@ hid_get_report_id(int fd)
if ((rep = hid_get_report_desc(fd)) == NULL)
goto use_ioctl;
kindset = 1 << hid_input | 1 << hid_output | 1 << hid_feature;
- for (d = hid_start_parse(rep, kindset, 0); hid_get_item(d, &h); ) {
+ for (d = hid_start_parse(rep, kindset, -1); hid_get_item(d, &h); ) {
/* Return the first report ID we met. */
if (h.report_ID != 0) {
temp = h.report_ID;
diff --git a/lib/libusbhid/parse.c b/lib/libusbhid/parse.c
index 041e289..7a2b3f4 100644
--- a/lib/libusbhid/parse.c
+++ b/lib/libusbhid/parse.c
@@ -70,6 +70,7 @@ struct hid_data {
uint8_t iusage; /* current "usages_min/max" index */
uint8_t ousage; /* current "usages_min/max" offset */
uint8_t susage; /* usage set flags */
+ int32_t reportid; /* requested report ID */
};
/*------------------------------------------------------------------------*
@@ -149,7 +150,7 @@ hid_switch_rid(struct hid_data *s, struct hid_item *c, int32_t next_rID)
* hid_start_parse
*------------------------------------------------------------------------*/
hid_data_t
-hid_start_parse(report_desc_t d, int kindset, int id __unused)
+hid_start_parse(report_desc_t d, int kindset, int id)
{
struct hid_data *s;
@@ -158,6 +159,7 @@ hid_start_parse(report_desc_t d, int kindset, int id __unused)
s->start = s->p = d->data;
s->end = d->data + d->size;
s->kindset = kindset;
+ s->reportid = id;
return (s);
}
@@ -207,8 +209,8 @@ hid_get_byte(struct hid_data *s, const uint16_t wSize)
/*------------------------------------------------------------------------*
* hid_get_item
*------------------------------------------------------------------------*/
-int
-hid_get_item(hid_data_t s, hid_item_t *h)
+static int
+hid_get_item_raw(hid_data_t s, hid_item_t *h)
{
hid_item_t *c;
unsigned int bTag, bType, bSize;
@@ -509,6 +511,19 @@ hid_get_item(hid_data_t s, hid_item_t *h)
}
int
+hid_get_item(hid_data_t s, hid_item_t *h)
+{
+ int r;
+
+ for (;;) {
+ r = hid_get_item_raw(s, h);
+ if (r <= 0 || s->reportid == -1 || h->report_ID == s->reportid)
+ break;
+ }
+ return (r);
+}
+
+int
hid_report_size(report_desc_t r, enum hid_kind k, int id)
{
struct hid_data *d;
@@ -523,7 +538,7 @@ hid_report_size(report_desc_t r, enum hid_kind k, int id)
memset(&h, 0, sizeof h);
for (d = hid_start_parse(r, 1 << k, id); hid_get_item(d, &h); ) {
- if ((h.report_ID == id || id < 0) && h.kind == k) {
+ if (h.kind == k) {
/* compute minimum */
if (lpos > h.pos)
lpos = h.pos;
diff --git a/lib/libusbhid/usbhid.3 b/lib/libusbhid/usbhid.3
index c34a109..98fcdf5 100644
--- a/lib/libusbhid/usbhid.3
+++ b/lib/libusbhid/usbhid.3
@@ -144,16 +144,15 @@ fails it will return
.Ss Descriptor Parsing Functions
To parse the report descriptor the
.Fn hid_start_parse
-function should be called with a report descriptor and a set that
-describes which items that are interesting.
+function should be called with a report descriptor, a set that
+describes which items that are interesting, and the desired report
+ID (or -1 to obtain items of all report IDs).
The set is obtained by OR-ing together values
.Fa "(1 << k)"
where
.Fa k
is an item of type
.Vt hid_kind_t .
-The report ID (if present) is given by
-.Fa id .
The function returns
.Dv NULL
if the initialization fails, otherwise an opaque value to be used
diff --git a/lib/libutil/Makefile b/lib/libutil/Makefile
index 413ba0b..582ccef 100644
--- a/lib/libutil/Makefile
+++ b/lib/libutil/Makefile
@@ -30,7 +30,7 @@ MAN+= expand_number.3 flopen.3 fparseln.3 hexdump.3 \
kinfo_getproc.3 kinfo_getvmmap.3 kld.3 login_auth.3 login_cap.3 \
login_class.3 login_ok.3 login_times.3 login_tty.3 pidfile.3 \
property.3 pty.3 quotafile.3 realhostname.3 realhostname_sa.3 \
- _secure_path.3 trimdomain.3 uucplock.3
+ _secure_path.3 trimdomain.3 uucplock.3 pw_util.3
MAN+= login.conf.5
MLINKS+= kld.3 kld_isloaded.3 kld.3 kld_load.3
MLINKS+=login_auth.3 auth_cat.3 login_auth.3 auth_checknologin.3
@@ -67,5 +67,18 @@ MLINKS+=quotafile.3 quota_close.3 \
quotafile.3 quota_write_usage.3
MLINKS+=uucplock.3 uu_lock.3 uucplock.3 uu_lock_txfr.3 \
uucplock.3 uu_lockerr.3 uucplock.3 uu_unlock.3
+MLINKS+=pw_util.3 pw_copy.3 \
+ pw_util.3 pw_dup.3 \
+ pw_util.3 pw_edit.3 \
+ pw_util.3 pw_equal.3 \
+ pw_util.3 pw_fini.3 \
+ pw_util.3 pw_init.3 \
+ pw_util.3 pw_make.3 \
+ pw_util.3 pw_make_v7.3 \
+ pw_util.3 pw_mkdb.3 \
+ pw_util.3 pw_lock.3 \
+ pw_util.3 pw_scan.3 \
+ pw_util.3 pw_tempname.3 \
+ pw_util.3 pw_tmp.3
.include <bsd.lib.mk>
diff --git a/lib/libutil/gr_util.c b/lib/libutil/gr_util.c
index 0173595..6d96d5e 100644
--- a/lib/libutil/gr_util.c
+++ b/lib/libutil/gr_util.c
@@ -63,6 +63,7 @@ static const char group_line_format[] = "%s:%s:%ju:";
int
gr_init(const char *dir, const char *group)
{
+
if (dir == NULL) {
strcpy(group_dir, _PATH_ETC);
} else {
@@ -88,6 +89,7 @@ gr_init(const char *dir, const char *group)
}
strcpy(group_file, group);
}
+
initialized = 1;
return (0);
}
diff --git a/lib/libutil/humanize_number.c b/lib/libutil/humanize_number.c
index 024bc6b..1cad1cf 100644
--- a/lib/libutil/humanize_number.c
+++ b/lib/libutil/humanize_number.c
@@ -76,7 +76,7 @@ humanize_number(char *buf, size_t len, int64_t quotient,
if (flags & HN_B)
prefixes = "B\0\0Ki\0Mi\0Gi\0Ti\0Pi\0Ei";
else
- prefixes = "\0\0Ki\0Mi\0Gi\0Ti\0Pi\0Ei";
+ prefixes = "\0\0\0Ki\0Mi\0Gi\0Ti\0Pi\0Ei";
} else {
baselen = 1;
if (flags & HN_DIVISOR_1000)
diff --git a/lib/libutil/pw_util.3 b/lib/libutil/pw_util.3
new file mode 100644
index 0000000..7ef0657
--- /dev/null
+++ b/lib/libutil/pw_util.3
@@ -0,0 +1,286 @@
+.\" Copyright (c) 2012 Baptiste Daroussin <bapt@FreeBSD.org>
+.\" 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 THE AUTHORS 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 AUTHORS 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.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd October 30, 2012
+.Dt PW_UTIL 3
+.Os
+.Sh NAME
+.Nm pw_copy ,
+.Nm pw_dup ,
+.Nm pw_edit ,
+.Nm pw_equal ,
+.Nm pw_fini ,
+.Nm pw_init ,
+.Nm pw_make ,
+.Nm pw_make_v7 ,
+.Nm pw_mkdb ,
+.Nm pw_lock ,
+.Nm pw_scan ,
+.Nm pw_tempname ,
+.Nm pw_tmp
+.Nd "functions for passwd file handling"
+.Sh LIBRARY
+.Lb libutil
+.Sh SYNOPSIS
+.In pwd.h
+.In libutil.h
+.Ft int
+.Fn pw_copy "int ffd" "int tfd" "const struct passwd *pw" "const struct passwd *oldpw"
+.Ft "struct passwd *"
+.Fn pw_dup "const struct passwd *pw"
+.Ft int
+.Fn pw_edit "int nosetuid"
+.Ft int
+.Fn pw_equal "const struct passwd *pw1" "const struct passwd pw2"
+.Ft void
+.Fn pw_fini "void"
+.Ft int
+.Fn pw_init "const char *dir" const char *master"
+.Ft "char *"
+.Fn pw_make "const struct passwd *pw"
+.Ft "char *"
+.Fn pw_make_v7 "const struct passwd *pw"
+.Ft int
+.Fn pw_mkdb "const char *user"
+.Ft int
+.Fn pw_lock "void"
+.Ft "struct passwd *"
+.Fn pw_scan "const char *line" "int flags"
+.Ft "const char *"
+.Fn pw_tempname "void"
+.Ft int
+.Fn pw_tmp "int mfd"
+.Sh DESCRIPTION
+The
+.Fn pw_copy
+function reads a password file from
+.Vt ffd
+and writes it back out to
+.Vt tfd
+possibly with modifications:
+.Bl -dash
+.It
+If
+.Fa pw
+is
+.Dv NULL
+and
+.Fa oldpw
+is not
+.Dv NULL ,
+then the record represented by
+.Fa oldpw
+will not be copied (corresponding to user deletion).
+.It
+If
+.Fa pw
+and
+.Fa oldpw
+are not
+.Dv NULL
+then the record corresponding to
+.Fa pw
+will be replaced by the record corresponding to
+.Fa oldpw .
+.It
+If
+.Vt pw
+is set and
+.Vt oldpw
+is
+.Dv NULL
+then the record corresponding to
+.Vt pw
+will be appended (corresponding to user addition).
+.El
+.Pp
+The
+.Fn pw_copy
+function returns -1 in case of failure otherwise 0.
+.Pp
+The
+.Fn pw_dup
+function duplicates the
+.Vt struct passwd
+pointed to by
+.Fa pw
+and returns a pointer to the copy, or
+.Dv NULL
+in case of failure.
+The new
+.Vt struct passwd
+is allocated with
+.Xr malloc 3 ,
+and it is the caller's responsibility to free it with
+.Xr free 3 .
+.Pp
+The
+.Fn pw_edit
+function invokes the command specified by the
+.Ev EDITOR
+environment variable (or
+.Pa /usr/bin/vi
+if
+.Ev EDITOR
+is not defined)
+on a temporary copy of the master password file created by
+.Fn pw_tmp .
+If the file was modified,
+.Fn pw_edit
+installs it and regenerates the password database.
+The
+.Fn pw_edit
+function returns -1 in case of failure, 0 if the file was not modified,
+and a non-zero positive number if the file was modified and successfully
+installed.
+.Pp
+The
+.Fn pw_equal
+function compares two
+.Vt struct passwd
+and returns 0 if they are equal.
+.Pp
+The
+.Fn pw_fini
+function destroy the temporary file created by
+.Fn pw_tmp
+if any,
+kills any running instance of
+.Ev EDITOR
+executed by
+.Fn pw_edit
+if any,
+and closes the lock created by
+.Fn pw_lock
+if any.
+.Pp
+The
+.Fn pw_init
+initialize the static variable representing the path a password file.
+.Fa dir
+is the directory where the password file is located.
+If set to
+.Dv NULL ,
+it will default to
+.Pa /etc .
+.Fa master
+is the name of the password file.
+If set to
+.Dv NULL?
+it will default to
+.Pa master.passwd
+.Pp
+The
+.Fn pw_make
+function creates a properly formatted
+.Bx
+.Xr passwd 5
+line from a
+.Vt struct passwd ,
+and returns a pointer to the resulting string.
+The string is allocated with
+.Xr malloc 3 ,
+and it is the caller's responsibility to free it with
+.Xr free 3 .
+.Pp
+The
+.Fn pw_make_v7
+function creates a properly formatted
+.Ux V7
+.Xr passwd 5
+line from a
+.Vt struct passwd ,
+and returns a pointer to the resulting string.
+The string is allocated with
+.Xr malloc 3 ,
+and it is the caller's responsibility to free it with
+.Xr free 3 .
+.Pp
+The
+.Fn pw_mkdb
+function regenerates the password database by running
+.Xr pw_mkdb 8 .
+If
+.Fa user
+only the record corresponding to that user will be updated.
+The
+.Fn pw_mkdb
+function returns 0 in case of success and -1 in case of failure.
+.Pp
+The
+.Fn pw_lock
+function locks the master password file.
+It returns 0 in case of success and -1 in case of failure.
+.Pp
+The
+.Fn pw_scan
+function is a wrapper around the internal libc function
+.Fn __pw_scan .
+It scans the master password file for a line corresponding to the
+.Fa line
+provided and return a
+.Vt struct passwd
+if it matched an existing record.
+In case of failure, it returns
+.Dv NULL .
+Otherwise, it returns a pointer to a
+.Vt struct passwd
+containing the matching record.
+The
+.Vt struct passwd
+is allocated with
+.Xr malloc 3 ,
+and it is the caller's responsibility to free it with
+.Xr free 3 .
+.Pp
+The
+.Fn pw_tempname
+function returns the temporary name of the masterfile created via
+.Fn pw_tmp .
+.Pp
+The
+.Fn pw_tmp
+creates and opens a presumably safe temporary password file.
+If
+.Fa mfd
+is a file descriptor to an open password file, it will be read and
+written back to the temporary password file.
+Otherwise if should be set -1.
+The
+.Fn pw_tmp
+returns an open file descriptor to the temporary password file or -1 in case of
+failure.
+.Sh AUTHORS
+Portions of this software were developed for the
+.Fx
+Project by ThinkSec AS and Network Associates Laboratories, the
+Security Research Division of Network Associates, Inc.\& under
+DARPA/SPAWAR contract N66001-01-C-8035
+.Pq Dq CBOSS ,
+as part of the DARPA CHATS research program.
+.Pp
+This manual page was written by
+.An Baptiste Daroussin Aq bapt@FreeBSD.org .
diff --git a/lib/msun/Makefile b/lib/msun/Makefile
index 0646dc0..a1ec6c9 100644
--- a/lib/msun/Makefile
+++ b/lib/msun/Makefile
@@ -94,7 +94,7 @@ COMMON_SRCS+= e_acosl.c e_asinl.c e_atan2l.c e_fmodl.c \
e_hypotl.c e_remainderl.c e_sqrtl.c \
invtrig.c k_cosl.c k_sinl.c k_tanl.c \
s_atanl.c s_cbrtl.c s_ceill.c s_cosl.c s_cprojl.c \
- s_csqrtl.c s_exp2l.c s_floorl.c s_fmal.c \
+ s_csqrtl.c s_exp2l.c s_expl.c s_floorl.c s_fmal.c \
s_frexpl.c s_logbl.c s_nanl.c s_nextafterl.c s_nexttoward.c \
s_remquol.c s_rintl.c s_scalbnl.c \
s_sinl.c s_tanl.c s_truncl.c w_cabsl.c
diff --git a/lib/msun/Symbol.map b/lib/msun/Symbol.map
index f3d3000..76f1bfb 100644
--- a/lib/msun/Symbol.map
+++ b/lib/msun/Symbol.map
@@ -249,4 +249,5 @@ FBSD_1.3 {
ctanf;
ctanh;
ctanhf;
+ expl;
};
diff --git a/lib/msun/i387/s_cos.S b/lib/msun/i387/s_cos.S
index 9c3f2ca..9951ab0 100644
--- a/lib/msun/i387/s_cos.S
+++ b/lib/msun/i387/s_cos.S
@@ -40,16 +40,16 @@ ENTRY(cos)
fldl 4(%esp)
fcos
fnstsw %ax
- andw $0x400,%ax
- jnz 1f
+ sahf
+ jp 1f
ret
1: fldpi
fadd %st(0)
fxch %st(1)
-2: fprem1
+2: fprem
fnstsw %ax
- andw $0x400,%ax
- jnz 2b
+ sahf
+ jp 2b
fstp %st(1)
fcos
ret
diff --git a/lib/msun/i387/s_sin.S b/lib/msun/i387/s_sin.S
index 11c4d63..eb04754 100644
--- a/lib/msun/i387/s_sin.S
+++ b/lib/msun/i387/s_sin.S
@@ -40,16 +40,16 @@ ENTRY(sin)
fldl 4(%esp)
fsin
fnstsw %ax
- andw $0x400,%ax
- jnz 1f
+ sahf
+ jp 1f
ret
1: fldpi
fadd %st(0)
fxch %st(1)
-2: fprem1
+2: fprem
fnstsw %ax
- andw $0x400,%ax
- jnz 2b
+ sahf
+ jp 2b
fstp %st(1)
fsin
ret
diff --git a/lib/msun/i387/s_tan.S b/lib/msun/i387/s_tan.S
index e31ebdf..182b9f7 100644
--- a/lib/msun/i387/s_tan.S
+++ b/lib/msun/i387/s_tan.S
@@ -40,17 +40,17 @@ ENTRY(tan)
fldl 4(%esp)
fptan
fnstsw %ax
- andw $0x400,%ax
- jnz 1f
+ sahf
+ jp 1f
fstp %st(0)
ret
1: fldpi
fadd %st(0)
fxch %st(1)
-2: fprem1
- fstsw %ax
- andw $0x400,%ax
- jnz 2b
+2: fprem
+ fnstsw %ax
+ sahf
+ jp 2b
fstp %st(1)
fptan
fstp %st(0)
diff --git a/lib/msun/ld128/s_expl.c b/lib/msun/ld128/s_expl.c
new file mode 100644
index 0000000..5052c3a
--- /dev/null
+++ b/lib/msun/ld128/s_expl.c
@@ -0,0 +1,261 @@
+/*-
+ * Copyright (c) 2012 Steven G. Kargl
+ * 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 unmodified, 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 THE AUTHOR ``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 AUTHOR 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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * ld128 version of s_expl.c. See ../ld80/s_expl.c for most comments.
+ */
+
+#include <float.h>
+
+#include "fpmath.h"
+#include "math.h"
+#include "math_private.h"
+
+#define INTERVALS 128
+#define BIAS (LDBL_MAX_EXP - 1)
+
+static volatile const long double tiny = 0x1p-10000L;
+
+static const long double
+INV_L = 1.84664965233787316142070359168242182e+02L,
+L1 = 5.41521234812457272982212595914567508e-03L,
+L2 = -1.02536706388947310094527932552595546e-29L,
+huge = 0x1p10000L,
+o_threshold = 11356.523406294143949491931077970763428L,
+twom10000 = 0x1p-10000L,
+u_threshold = -11433.462743336297878837243843452621503L;
+
+static const long double
+P2 = 5.00000000000000000000000000000000000e-1L,
+P3 = 1.66666666666666666666666666666666972e-1L,
+P4 = 4.16666666666666666666666666653708268e-2L,
+P5 = 8.33333333333333333333333315069867254e-3L,
+P6 = 1.38888888888888888888996596213795377e-3L,
+P7 = 1.98412698412698412718821436278644414e-4L,
+P8 = 2.48015873015869681884882576649543128e-5L,
+P9 = 2.75573192240103867817876199544468806e-6L,
+P10 = 2.75573236172670046201884000197885520e-7L,
+P11 = 2.50517544183909126492878226167697856e-8L;
+
+static const struct {
+ long double hi;
+ long double lo;
+} s[INTERVALS] = {
+ 0x1p0L, 0x0p0L,
+ 0x1.0163da9fb33356d84a66aep0L, 0x3.36dcdfa4003ec04c360be2404078p-92L,
+ 0x1.02c9a3e778060ee6f7cacap0L, 0x4.f7a29bde93d70a2cabc5cb89ba10p-92L,
+ 0x1.04315e86e7f84bd738f9a2p0L, 0xd.a47e6ed040bb4bfc05af6455e9b8p-96L,
+ 0x1.059b0d31585743ae7c548ep0L, 0xb.68ca417fe53e3495f7df4baf84a0p-92L,
+ 0x1.0706b29ddf6ddc6dc403a8p0L, 0x1.d87b27ed07cb8b092ac75e311753p-88L,
+ 0x1.0874518759bc808c35f25cp0L, 0x1.9427fa2b041b2d6829d8993a0d01p-88L,
+ 0x1.09e3ecac6f3834521e060cp0L, 0x5.84d6b74ba2e023da730e7fccb758p-92L,
+ 0x1.0b5586cf9890f6298b92b6p0L, 0x1.1842a98364291408b3ceb0a2a2bbp-88L,
+ 0x1.0cc922b7247f7407b705b8p0L, 0x9.3dc5e8aac564e6fe2ef1d431fd98p-92L,
+ 0x1.0e3ec32d3d1a2020742e4ep0L, 0x1.8af6a552ac4b358b1129e9f966a4p-88L,
+ 0x1.0fb66affed31af232091dcp0L, 0x1.8a1426514e0b627bda694a400a27p-88L,
+ 0x1.11301d0125b50a4ebbf1aep0L, 0xd.9318ceac5cc47ab166ee57427178p-92L,
+ 0x1.12abdc06c31cbfb92bad32p0L, 0x4.d68e2f7270bdf7cedf94eb1cb818p-92L,
+ 0x1.1429aaea92ddfb34101942p0L, 0x1.b2586d01844b389bea7aedd221d4p-88L,
+ 0x1.15a98c8a58e512480d573cp0L, 0x1.d5613bf92a2b618ee31b376c2689p-88L,
+ 0x1.172b83c7d517adcdf7c8c4p0L, 0x1.0eb14a792035509ff7d758693f24p-88L,
+ 0x1.18af9388c8de9bbbf70b9ap0L, 0x3.c2505c97c0102e5f1211941d2840p-92L,
+ 0x1.1a35beb6fcb753cb698f68p0L, 0x1.2d1c835a6c30724d5cfae31b84e5p-88L,
+ 0x1.1bbe084045cd39ab1e72b4p0L, 0x4.27e35f9acb57e473915519a1b448p-92L,
+ 0x1.1d4873168b9aa7805b8028p0L, 0x9.90f07a98b42206e46166cf051d70p-92L,
+ 0x1.1ed5022fcd91cb8819ff60p0L, 0x1.121d1e504d36c47474c9b7de6067p-88L,
+ 0x1.2063b88628cd63b8eeb028p0L, 0x1.50929d0fc487d21c2b84004264dep-88L,
+ 0x1.21f49917ddc962552fd292p0L, 0x9.4bdb4b61ea62477caa1dce823ba0p-92L,
+ 0x1.2387a6e75623866c1fadb0p0L, 0x1.c15cb593b0328566902df69e4de2p-88L,
+ 0x1.251ce4fb2a63f3582ab7dep0L, 0x9.e94811a9c8afdcf796934bc652d0p-92L,
+ 0x1.26b4565e27cdd257a67328p0L, 0x1.d3b249dce4e9186ddd5ff44e6b08p-92L,
+ 0x1.284dfe1f5638096cf15cf0p0L, 0x3.ca0967fdaa2e52d7c8106f2e262cp-92L,
+ 0x1.29e9df51fdee12c25d15f4p0L, 0x1.a24aa3bca890ac08d203fed80a07p-88L,
+ 0x1.2b87fd0dad98ffddea4652p0L, 0x1.8fcab88442fdc3cb6de4519165edp-88L,
+ 0x1.2d285a6e4030b40091d536p0L, 0xd.075384589c1cd1b3e4018a6b1348p-92L,
+ 0x1.2ecafa93e2f5611ca0f45cp0L, 0x1.523833af611bdcda253c554cf278p-88L,
+ 0x1.306fe0a31b7152de8d5a46p0L, 0x3.05c85edecbc27343629f502f1af2p-92L,
+ 0x1.32170fc4cd8313539cf1c2p0L, 0x1.008f86dde3220ae17a005b6412bep-88L,
+ 0x1.33c08b26416ff4c9c8610cp0L, 0x1.96696bf95d1593039539d94d662bp-88L,
+ 0x1.356c55f929ff0c94623476p0L, 0x3.73af38d6d8d6f9506c9bbc93cbc0p-92L,
+ 0x1.371a7373aa9caa7145502ep0L, 0x1.4547987e3e12516bf9c699be432fp-88L,
+ 0x1.38cae6d05d86585a9cb0d8p0L, 0x1.bed0c853bd30a02790931eb2e8f0p-88L,
+ 0x1.3a7db34e59ff6ea1bc9298p0L, 0x1.e0a1d336163fe2f852ceeb134067p-88L,
+ 0x1.3c32dc313a8e484001f228p0L, 0xb.58f3775e06ab66353001fae9fca0p-92L,
+ 0x1.3dea64c12342235b41223ep0L, 0x1.3d773fba2cb82b8244267c54443fp-92L,
+ 0x1.3fa4504ac801ba0bf701aap0L, 0x4.1832fb8c1c8dbdff2c49909e6c60p-92L,
+ 0x1.4160a21f72e29f84325b8ep0L, 0x1.3db61fb352f0540e6ba05634413ep-88L,
+ 0x1.431f5d950a896dc7044394p0L, 0x1.0ccec81e24b0caff7581ef4127f7p-92L,
+ 0x1.44e086061892d03136f408p0L, 0x1.df019fbd4f3b48709b78591d5cb5p-88L,
+ 0x1.46a41ed1d005772512f458p0L, 0x1.229d97df404ff21f39c1b594d3a8p-88L,
+ 0x1.486a2b5c13cd013c1a3b68p0L, 0x1.062f03c3dd75ce8757f780e6ec99p-88L,
+ 0x1.4a32af0d7d3de672d8bcf4p0L, 0x6.f9586461db1d878b1d148bd3ccb8p-92L,
+ 0x1.4bfdad5362a271d4397afep0L, 0xc.42e20e0363ba2e159c579f82e4b0p-92L,
+ 0x1.4dcb299fddd0d63b36ef1ap0L, 0x9.e0cc484b25a5566d0bd5f58ad238p-92L,
+ 0x1.4f9b2769d2ca6ad33d8b68p0L, 0x1.aa073ee55e028497a329a7333dbap-88L,
+ 0x1.516daa2cf6641c112f52c8p0L, 0x4.d822190e718226177d7608d20038p-92L,
+ 0x1.5342b569d4f81df0a83c48p0L, 0x1.d86a63f4e672a3e429805b049465p-88L,
+ 0x1.551a4ca5d920ec52ec6202p0L, 0x4.34ca672645dc6c124d6619a87574p-92L,
+ 0x1.56f4736b527da66ecb0046p0L, 0x1.64eb3c00f2f5ab3d801d7cc7272dp-88L,
+ 0x1.58d12d497c7fd252bc2b72p0L, 0x1.43bcf2ec936a970d9cc266f0072fp-88L,
+ 0x1.5ab07dd48542958c930150p0L, 0x1.91eb345d88d7c81280e069fbdb63p-88L,
+ 0x1.5c9268a5946b701c4b1b80p0L, 0x1.6986a203d84e6a4a92f179e71889p-88L,
+ 0x1.5e76f15ad21486e9be4c20p0L, 0x3.99766a06548a05829e853bdb2b52p-92L,
+ 0x1.605e1b976dc08b076f592ap0L, 0x4.86e3b34ead1b4769df867b9c89ccp-92L,
+ 0x1.6247eb03a5584b1f0fa06ep0L, 0x1.d2da42bb1ceaf9f732275b8aef30p-88L,
+ 0x1.6434634ccc31fc76f8714cp0L, 0x4.ed9a4e41000307103a18cf7a6e08p-92L,
+ 0x1.66238825522249127d9e28p0L, 0x1.b8f314a337f4dc0a3adf1787ff74p-88L,
+ 0x1.68155d44ca973081c57226p0L, 0x1.b9f32706bfe4e627d809a85dcc66p-88L,
+ 0x1.6a09e667f3bcc908b2fb12p0L, 0x1.66ea957d3e3adec17512775099dap-88L,
+ 0x1.6c012750bdabeed76a9980p0L, 0xf.4f33fdeb8b0ecd831106f57b3d00p-96L,
+ 0x1.6dfb23c651a2ef220e2cbep0L, 0x1.bbaa834b3f11577ceefbe6c1c411p-92L,
+ 0x1.6ff7df9519483cf87e1b4ep0L, 0x1.3e213bff9b702d5aa477c12523cep-88L,
+ 0x1.71f75e8ec5f73dd2370f2ep0L, 0xf.0acd6cb434b562d9e8a20adda648p-92L,
+ 0x1.73f9a48a58173bd5c9a4e6p0L, 0x8.ab1182ae217f3a7681759553e840p-92L,
+ 0x1.75feb564267c8bf6e9aa32p0L, 0x1.a48b27071805e61a17b954a2dad8p-88L,
+ 0x1.780694fde5d3f619ae0280p0L, 0x8.58b2bb2bdcf86cd08e35fb04c0f0p-92L,
+ 0x1.7a11473eb0186d7d51023ep0L, 0x1.6cda1f5ef42b66977960531e821bp-88L,
+ 0x1.7c1ed0130c1327c4933444p0L, 0x1.937562b2dc933d44fc828efd4c9cp-88L,
+ 0x1.7e2f336cf4e62105d02ba0p0L, 0x1.5797e170a1427f8fcdf5f3906108p-88L,
+ 0x1.80427543e1a11b60de6764p0L, 0x9.a354ea706b8e4d8b718a672bf7c8p-92L,
+ 0x1.82589994cce128acf88afap0L, 0xb.34a010f6ad65cbbac0f532d39be0p-92L,
+ 0x1.8471a4623c7acce52f6b96p0L, 0x1.c64095370f51f48817914dd78665p-88L,
+ 0x1.868d99b4492ec80e41d90ap0L, 0xc.251707484d73f136fb5779656b70p-92L,
+ 0x1.88ac7d98a669966530bcdep0L, 0x1.2d4e9d61283ef385de170ab20f96p-88L,
+ 0x1.8ace5422aa0db5ba7c55a0p0L, 0x1.92c9bb3e6ed61f2733304a346d8fp-88L,
+ 0x1.8cf3216b5448bef2aa1cd0p0L, 0x1.61c55d84a9848f8c453b3ca8c946p-88L,
+ 0x1.8f1ae991577362b982745cp0L, 0x7.2ed804efc9b4ae1458ae946099d4p-92L,
+ 0x1.9145b0b91ffc588a61b468p0L, 0x1.f6b70e01c2a90229a4c4309ea719p-88L,
+ 0x1.93737b0cdc5e4f4501c3f2p0L, 0x5.40a22d2fc4af581b63e8326efe9cp-92L,
+ 0x1.95a44cbc8520ee9b483694p0L, 0x1.a0fc6f7c7d61b2b3a22a0eab2cadp-88L,
+ 0x1.97d829fde4e4f8b9e920f8p0L, 0x1.1e8bd7edb9d7144b6f6818084cc7p-88L,
+ 0x1.9a0f170ca07b9ba3109b8cp0L, 0x4.6737beb19e1eada6825d3c557428p-92L,
+ 0x1.9c49182a3f0901c7c46b06p0L, 0x1.1f2be58ddade50c217186c90b457p-88L,
+ 0x1.9e86319e323231824ca78ep0L, 0x6.4c6e010f92c082bbadfaf605cfd4p-92L,
+ 0x1.a0c667b5de564b29ada8b8p0L, 0xc.ab349aa0422a8da7d4512edac548p-92L,
+ 0x1.a309bec4a2d3358c171f76p0L, 0x1.0daad547fa22c26d168ea762d854p-88L,
+ 0x1.a5503b23e255c8b424491cp0L, 0xa.f87bc8050a405381703ef7caff50p-92L,
+ 0x1.a799e1330b3586f2dfb2b0p0L, 0x1.58f1a98796ce8908ae852236ca94p-88L,
+ 0x1.a9e6b5579fdbf43eb243bcp0L, 0x1.ff4c4c58b571cf465caf07b4b9f5p-88L,
+ 0x1.ac36bbfd3f379c0db966a2p0L, 0x1.1265fc73e480712d20f8597a8e7bp-88L,
+ 0x1.ae89f995ad3ad5e8734d16p0L, 0x1.73205a7fbc3ae675ea440b162d6cp-88L,
+ 0x1.b0e07298db66590842acdep0L, 0x1.c6f6ca0e5dcae2aafffa7a0554cbp-88L,
+ 0x1.b33a2b84f15faf6bfd0e7ap0L, 0x1.d947c2575781dbb49b1237c87b6ep-88L,
+ 0x1.b59728de559398e3881110p0L, 0x1.64873c7171fefc410416be0a6525p-88L,
+ 0x1.b7f76f2fb5e46eaa7b081ap0L, 0xb.53c5354c8903c356e4b625aacc28p-92L,
+ 0x1.ba5b030a10649840cb3c6ap0L, 0xf.5b47f297203757e1cc6eadc8bad0p-92L,
+ 0x1.bcc1e904bc1d2247ba0f44p0L, 0x1.b3d08cd0b20287092bd59be4ad98p-88L,
+ 0x1.bf2c25bd71e088408d7024p0L, 0x1.18e3449fa073b356766dfb568ff4p-88L,
+ 0x1.c199bdd85529c2220cb12ap0L, 0x9.1ba6679444964a36661240043970p-96L,
+ 0x1.c40ab5fffd07a6d14df820p0L, 0xf.1828a5366fd387a7bdd54cdf7300p-92L,
+ 0x1.c67f12e57d14b4a2137fd2p0L, 0xf.2b301dd9e6b151a6d1f9d5d5f520p-96L,
+ 0x1.c8f6d9406e7b511acbc488p0L, 0x5.c442ddb55820171f319d9e5076a8p-96L,
+ 0x1.cb720dcef90691503cbd1ep0L, 0x9.49db761d9559ac0cb6dd3ed599e0p-92L,
+ 0x1.cdf0b555dc3f9c44f8958ep0L, 0x1.ac51be515f8c58bdfb6f5740a3a4p-88L,
+ 0x1.d072d4a07897b8d0f22f20p0L, 0x1.a158e18fbbfc625f09f4cca40874p-88L,
+ 0x1.d2f87080d89f18ade12398p0L, 0x9.ea2025b4c56553f5cdee4c924728p-92L,
+ 0x1.d5818dcfba48725da05aeap0L, 0x1.66e0dca9f589f559c0876ff23830p-88L,
+ 0x1.d80e316c98397bb84f9d04p0L, 0x8.805f84bec614de269900ddf98d28p-92L,
+ 0x1.da9e603db3285708c01a5ap0L, 0x1.6d4c97f6246f0ec614ec95c99392p-88L,
+ 0x1.dd321f301b4604b695de3cp0L, 0x6.30a393215299e30d4fb73503c348p-96L,
+ 0x1.dfc97337b9b5eb968cac38p0L, 0x1.ed291b7225a944efd5bb5524b927p-88L,
+ 0x1.e264614f5a128a12761fa0p0L, 0x1.7ada6467e77f73bf65e04c95e29dp-88L,
+ 0x1.e502ee78b3ff6273d13014p0L, 0x1.3991e8f49659e1693be17ae1d2f9p-88L,
+ 0x1.e7a51fbc74c834b548b282p0L, 0x1.23786758a84f4956354634a416cep-88L,
+ 0x1.ea4afa2a490d9858f73a18p0L, 0xf.5db301f86dea20610ceee13eb7b8p-92L,
+ 0x1.ecf482d8e67f08db0312fap0L, 0x1.949cef462010bb4bc4ce72a900dfp-88L,
+ 0x1.efa1bee615a27771fd21a8p0L, 0x1.2dac1f6dd5d229ff68e46f27e3dfp-88L,
+ 0x1.f252b376bba974e8696fc2p0L, 0x1.6390d4c6ad5476b5162f40e1d9a9p-88L,
+ 0x1.f50765b6e4540674f84b76p0L, 0x2.862baff99000dfc4352ba29b8908p-92L,
+ 0x1.f7bfdad9cbe138913b4bfep0L, 0x7.2bd95c5ce7280fa4d2344a3f5618p-92L,
+ 0x1.fa7c1819e90d82e90a7e74p0L, 0xb.263c1dc060c36f7650b4c0f233a8p-92L,
+ 0x1.fd3c22b8f71f10975ba4b2p0L, 0x1.2bcf3a5e12d269d8ad7c1a4a8875p-88L
+};
+
+long double
+expl(long double x)
+{
+ union IEEEl2bits u, v;
+ long double fn, r, r1, r2, q, t, twopk, twopkp10000;
+ int k, n, n2;
+ uint32_t hx, ix;
+
+ /* Filter out exceptional cases. */
+ u.e = x;
+ hx = u.xbits.expsign;
+ ix = hx & 0x7fff;
+ if (ix >= BIAS + 13) { /* |x| >= 8192 or x is NaN */
+ if (ix == BIAS + LDBL_MAX_EXP) {
+ if (hx & 0x8000 && u.xbits.manh == 0 &&
+ u.xbits.manl == 0)
+ return (0.0L); /* x is -Inf */
+ return (x + x); /* x is +Inf or NaN */
+ }
+ if (x > o_threshold)
+ return (huge * huge);
+ if (x < u_threshold)
+ return (tiny * tiny);
+ } else if (ix < BIAS - 115) { /* |x| < 0x1p-115 */
+ if (huge + x > 1.0L) /* trigger inexact iff x != 0 */
+ return (1.0L + x);
+ }
+
+ /* Reduce x to (k*ln2 + midpoint[n2] + r1 + r2). */
+ fn = x * INV_L + 0x1.8p112 - 0x1.8p112;
+ n = (int)fn;
+ n2 = (unsigned)n % INTERVALS;
+ k = (n - n2) / INTERVALS;
+ r1 = x - fn * L1;
+ r2 = -fn * L2;
+
+ /* Prepare scale factors. */
+ v.xbits.manh = 0;
+ v.xbits.manl = 0;
+ if (k >= LDBL_MIN_EXP) {
+ v.xbits.expsign = BIAS + k;
+ twopk = v.e;
+ } else {
+ v.xbits.expsign = BIAS + k + 10000;
+ twopkp10000 = v.e;
+ }
+
+ r = r1 + r2;
+ q = r * r * (P2 + r * (P3 + r * (P4 + r * (P5 + r * (P6 + r * (P7 +
+ r * (P8 + r * (P9 + r * (P10 + r * P11)))))))));
+ t = s[n2].lo + s[n2].hi;
+ t = s[n2].hi + (s[n2].lo + t * (r2 + q + r1));
+
+ /* Scale by 2**k. */
+ if (k >= LDBL_MIN_EXP) {
+ if (k == LDBL_MAX_EXP)
+ return (t * 2.0L * 0x1p16383L);
+ return (t * twopk);
+ } else {
+ return (t * twopkp10000 * twom10000);
+ }
+}
diff --git a/lib/msun/ld80/s_expl.c b/lib/msun/ld80/s_expl.c
new file mode 100644
index 0000000..af63668
--- /dev/null
+++ b/lib/msun/ld80/s_expl.c
@@ -0,0 +1,304 @@
+/*-
+ * Copyright (c) 2009-2012 Steven G. Kargl
+ * 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 unmodified, 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 THE AUTHOR ``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 AUTHOR 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.
+ *
+ * Optimized by Bruce D. Evans.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*-
+ * Compute the exponential of x for Intel 80-bit format. This is based on:
+ *
+ * PTP Tang, "Table-driven implementation of the exponential function
+ * in IEEE floating-point arithmetic," ACM Trans. Math. Soft., 15,
+ * 144-157 (1989).
+ *
+ * where the 32 table entries have been expanded to INTERVALS (see below).
+ */
+
+#include <float.h>
+
+#ifdef __i386__
+#include <ieeefp.h>
+#endif
+
+#include "fpmath.h"
+#include "math.h"
+#include "math_private.h"
+
+#define INTERVALS 128
+#define BIAS (LDBL_MAX_EXP - 1)
+
+static const long double
+huge = 0x1p10000L,
+twom10000 = 0x1p-10000L;
+/* XXX Prevent gcc from erroneously constant folding this: */
+static volatile const long double tiny = 0x1p-10000L;
+
+static const union IEEEl2bits
+/* log(2**16384 - 0.5) rounded towards zero: */
+o_threshold = LD80C(0xb17217f7d1cf79ab, 13, 11356.5234062941439488L),
+/* log(2**(-16381-64-1)) rounded towards zero: */
+u_threshold = LD80C(0xb21dfe7f09e2baa9, 13, -11399.4985314888605581L);
+
+static const double
+/*
+ * ln2/INTERVALS = L1+L2 (hi+lo decomposition for multiplication). L1 must
+ * have at least 22 (= log2(|LDBL_MIN_EXP-extras|) + log2(INTERVALS)) lowest
+ * bits zero so that multiplication of it by n is exact.
+ */
+INV_L = 1.8466496523378731e+2, /* 0x171547652b82fe.0p-45 */
+L1 = 5.4152123484527692e-3, /* 0x162e42ff000000.0p-60 */
+L2 = -3.2819649005320973e-13, /* -0x1718432a1b0e26.0p-94 */
+/*
+ * Domain [-0.002708, 0.002708], range ~[-5.7136e-24, 5.7110e-24]:
+ * |exp(x) - p(x)| < 2**-77.2
+ * (0.002708 is ln2/(2*INTERVALS) rounded up a little).
+ */
+P2 = 0.5,
+P3 = 1.6666666666666119e-1, /* 0x15555555555490.0p-55 */
+P4 = 4.1666666666665887e-2, /* 0x155555555554e5.0p-57 */
+P5 = 8.3333354987869413e-3, /* 0x1111115b789919.0p-59 */
+P6 = 1.3888891738560272e-3; /* 0x16c16c651633ae.0p-62 */
+
+/*
+ * 2^(i/INTERVALS) for i in [0,INTERVALS] is represented by two values where
+ * the first 53 bits of the significand are stored in hi and the next 53
+ * bits are in lo. Tang's paper states that the trailing 6 bits of hi must
+ * be zero for his algorithm in both single and double precision, because
+ * the table is re-used in the implementation of expm1() where a floating
+ * point addition involving hi must be exact. Here hi is double, so
+ * converting it to long double gives 11 trailing zero bits.
+ */
+static const struct {
+ double hi;
+ double lo;
+/* XXX should rename 's'. */
+} s[INTERVALS] = {
+ 0x1p+0, 0x0p+0,
+ 0x1.0163da9fb3335p+0, 0x1.b61299ab8cdb7p-54,
+ 0x1.02c9a3e778060p+0, 0x1.dcdef95949ef4p-53,
+ 0x1.04315e86e7f84p+0, 0x1.7ae71f3441b49p-53,
+ 0x1.059b0d3158574p+0, 0x1.d73e2a475b465p-55,
+ 0x1.0706b29ddf6ddp+0, 0x1.8db880753b0f6p-53,
+ 0x1.0874518759bc8p+0, 0x1.186be4bb284ffp-57,
+ 0x1.09e3ecac6f383p+0, 0x1.1487818316136p-54,
+ 0x1.0b5586cf9890fp+0, 0x1.8a62e4adc610bp-54,
+ 0x1.0cc922b7247f7p+0, 0x1.01edc16e24f71p-54,
+ 0x1.0e3ec32d3d1a2p+0, 0x1.03a1727c57b53p-59,
+ 0x1.0fb66affed31ap+0, 0x1.e464123bb1428p-53,
+ 0x1.11301d0125b50p+0, 0x1.49d77e35db263p-53,
+ 0x1.12abdc06c31cbp+0, 0x1.f72575a649ad2p-53,
+ 0x1.1429aaea92ddfp+0, 0x1.66820328764b1p-53,
+ 0x1.15a98c8a58e51p+0, 0x1.2406ab9eeab0ap-55,
+ 0x1.172b83c7d517ap+0, 0x1.b9bef918a1d63p-53,
+ 0x1.18af9388c8de9p+0, 0x1.777ee1734784ap-53,
+ 0x1.1a35beb6fcb75p+0, 0x1.e5b4c7b4968e4p-55,
+ 0x1.1bbe084045cd3p+0, 0x1.3563ce56884fcp-53,
+ 0x1.1d4873168b9aap+0, 0x1.e016e00a2643cp-54,
+ 0x1.1ed5022fcd91cp+0, 0x1.71033fec2243ap-53,
+ 0x1.2063b88628cd6p+0, 0x1.dc775814a8495p-55,
+ 0x1.21f49917ddc96p+0, 0x1.2a97e9494a5eep-55,
+ 0x1.2387a6e756238p+0, 0x1.9b07eb6c70573p-54,
+ 0x1.251ce4fb2a63fp+0, 0x1.ac155bef4f4a4p-55,
+ 0x1.26b4565e27cddp+0, 0x1.2bd339940e9d9p-55,
+ 0x1.284dfe1f56380p+0, 0x1.2d9e2b9e07941p-53,
+ 0x1.29e9df51fdee1p+0, 0x1.612e8afad1255p-55,
+ 0x1.2b87fd0dad98fp+0, 0x1.fbbd48ca71f95p-53,
+ 0x1.2d285a6e4030bp+0, 0x1.0024754db41d5p-54,
+ 0x1.2ecafa93e2f56p+0, 0x1.1ca0f45d52383p-56,
+ 0x1.306fe0a31b715p+0, 0x1.6f46ad23182e4p-55,
+ 0x1.32170fc4cd831p+0, 0x1.a9ce78e18047cp-55,
+ 0x1.33c08b26416ffp+0, 0x1.32721843659a6p-54,
+ 0x1.356c55f929ff0p+0, 0x1.928c468ec6e76p-53,
+ 0x1.371a7373aa9cap+0, 0x1.4e28aa05e8a8fp-53,
+ 0x1.38cae6d05d865p+0, 0x1.0b53961b37da2p-53,
+ 0x1.3a7db34e59ff6p+0, 0x1.d43792533c144p-53,
+ 0x1.3c32dc313a8e4p+0, 0x1.08003e4516b1ep-53,
+ 0x1.3dea64c123422p+0, 0x1.ada0911f09ebcp-55,
+ 0x1.3fa4504ac801bp+0, 0x1.417ee03548306p-53,
+ 0x1.4160a21f72e29p+0, 0x1.f0864b71e7b6cp-53,
+ 0x1.431f5d950a896p+0, 0x1.b8e088728219ap-53,
+ 0x1.44e086061892dp+0, 0x1.89b7a04ef80d0p-59,
+ 0x1.46a41ed1d0057p+0, 0x1.c944bd1648a76p-54,
+ 0x1.486a2b5c13cd0p+0, 0x1.3c1a3b69062f0p-56,
+ 0x1.4a32af0d7d3dep+0, 0x1.9cb62f3d1be56p-54,
+ 0x1.4bfdad5362a27p+0, 0x1.d4397afec42e2p-56,
+ 0x1.4dcb299fddd0dp+0, 0x1.8ecdbbc6a7833p-54,
+ 0x1.4f9b2769d2ca6p+0, 0x1.5a67b16d3540ep-53,
+ 0x1.516daa2cf6641p+0, 0x1.8225ea5909b04p-53,
+ 0x1.5342b569d4f81p+0, 0x1.be1507893b0d5p-53,
+ 0x1.551a4ca5d920ep+0, 0x1.8a5d8c4048699p-53,
+ 0x1.56f4736b527dap+0, 0x1.9bb2c011d93adp-54,
+ 0x1.58d12d497c7fdp+0, 0x1.295e15b9a1de8p-55,
+ 0x1.5ab07dd485429p+0, 0x1.6324c054647adp-54,
+ 0x1.5c9268a5946b7p+0, 0x1.c4b1b816986a2p-60,
+ 0x1.5e76f15ad2148p+0, 0x1.ba6f93080e65ep-54,
+ 0x1.605e1b976dc08p+0, 0x1.60edeb25490dcp-53,
+ 0x1.6247eb03a5584p+0, 0x1.63e1f40dfa5b5p-53,
+ 0x1.6434634ccc31fp+0, 0x1.8edf0e2989db3p-53,
+ 0x1.6623882552224p+0, 0x1.224fb3c5371e6p-53,
+ 0x1.68155d44ca973p+0, 0x1.038ae44f73e65p-57,
+ 0x1.6a09e667f3bccp+0, 0x1.21165f626cdd5p-53,
+ 0x1.6c012750bdabep+0, 0x1.daed533001e9ep-53,
+ 0x1.6dfb23c651a2ep+0, 0x1.e441c597c3775p-53,
+ 0x1.6ff7df9519483p+0, 0x1.9f0fc369e7c42p-53,
+ 0x1.71f75e8ec5f73p+0, 0x1.ba46e1e5de15ap-53,
+ 0x1.73f9a48a58173p+0, 0x1.7ab9349cd1562p-53,
+ 0x1.75feb564267c8p+0, 0x1.7edd354674916p-53,
+ 0x1.780694fde5d3fp+0, 0x1.866b80a02162dp-54,
+ 0x1.7a11473eb0186p+0, 0x1.afaa2047ed9b4p-53,
+ 0x1.7c1ed0130c132p+0, 0x1.f124cd1164dd6p-54,
+ 0x1.7e2f336cf4e62p+0, 0x1.05d02ba15797ep-56,
+ 0x1.80427543e1a11p+0, 0x1.6c1bccec9346bp-53,
+ 0x1.82589994cce12p+0, 0x1.159f115f56694p-53,
+ 0x1.8471a4623c7acp+0, 0x1.9ca5ed72f8c81p-53,
+ 0x1.868d99b4492ecp+0, 0x1.01c83b21584a3p-53,
+ 0x1.88ac7d98a6699p+0, 0x1.994c2f37cb53ap-54,
+ 0x1.8ace5422aa0dbp+0, 0x1.6e9f156864b27p-54,
+ 0x1.8cf3216b5448bp+0, 0x1.de55439a2c38bp-53,
+ 0x1.8f1ae99157736p+0, 0x1.5cc13a2e3976cp-55,
+ 0x1.9145b0b91ffc5p+0, 0x1.114c368d3ed6ep-53,
+ 0x1.93737b0cdc5e4p+0, 0x1.e8a0387e4a814p-53,
+ 0x1.95a44cbc8520ep+0, 0x1.d36906d2b41f9p-53,
+ 0x1.97d829fde4e4fp+0, 0x1.173d241f23d18p-53,
+ 0x1.9a0f170ca07b9p+0, 0x1.7462137188ce7p-53,
+ 0x1.9c49182a3f090p+0, 0x1.c7c46b071f2bep-56,
+ 0x1.9e86319e32323p+0, 0x1.824ca78e64c6ep-56,
+ 0x1.a0c667b5de564p+0, 0x1.6535b51719567p-53,
+ 0x1.a309bec4a2d33p+0, 0x1.6305c7ddc36abp-54,
+ 0x1.a5503b23e255cp+0, 0x1.1684892395f0fp-53,
+ 0x1.a799e1330b358p+0, 0x1.bcb7ecac563c7p-54,
+ 0x1.a9e6b5579fdbfp+0, 0x1.0fac90ef7fd31p-54,
+ 0x1.ac36bbfd3f379p+0, 0x1.81b72cd4624ccp-53,
+ 0x1.ae89f995ad3adp+0, 0x1.7a1cd345dcc81p-54,
+ 0x1.b0e07298db665p+0, 0x1.2108559bf8deep-53,
+ 0x1.b33a2b84f15fap+0, 0x1.ed7fa1cf7b290p-53,
+ 0x1.b59728de55939p+0, 0x1.1c7102222c90ep-53,
+ 0x1.b7f76f2fb5e46p+0, 0x1.d54f610356a79p-53,
+ 0x1.ba5b030a10649p+0, 0x1.0819678d5eb69p-53,
+ 0x1.bcc1e904bc1d2p+0, 0x1.23dd07a2d9e84p-55,
+ 0x1.bf2c25bd71e08p+0, 0x1.0811ae04a31c7p-53,
+ 0x1.c199bdd85529cp+0, 0x1.11065895048ddp-55,
+ 0x1.c40ab5fffd07ap+0, 0x1.b4537e083c60ap-54,
+ 0x1.c67f12e57d14bp+0, 0x1.2884dff483cadp-54,
+ 0x1.c8f6d9406e7b5p+0, 0x1.1acbc48805c44p-56,
+ 0x1.cb720dcef9069p+0, 0x1.503cbd1e949dbp-56,
+ 0x1.cdf0b555dc3f9p+0, 0x1.889f12b1f58a3p-53,
+ 0x1.d072d4a07897bp+0, 0x1.1a1e45e4342b2p-53,
+ 0x1.d2f87080d89f1p+0, 0x1.15bc247313d44p-53,
+ 0x1.d5818dcfba487p+0, 0x1.2ed02d75b3707p-55,
+ 0x1.d80e316c98397p+0, 0x1.7709f3a09100cp-53,
+ 0x1.da9e603db3285p+0, 0x1.c2300696db532p-54,
+ 0x1.dd321f301b460p+0, 0x1.2da5778f018c3p-54,
+ 0x1.dfc97337b9b5ep+0, 0x1.72d195873da52p-53,
+ 0x1.e264614f5a128p+0, 0x1.424ec3f42f5b5p-53,
+ 0x1.e502ee78b3ff6p+0, 0x1.39e8980a9cc8fp-55,
+ 0x1.e7a51fbc74c83p+0, 0x1.2d522ca0c8de2p-54,
+ 0x1.ea4afa2a490d9p+0, 0x1.0b1ee7431ebb6p-53,
+ 0x1.ecf482d8e67f0p+0, 0x1.1b60625f7293ap-53,
+ 0x1.efa1bee615a27p+0, 0x1.dc7f486a4b6b0p-54,
+ 0x1.f252b376bba97p+0, 0x1.3a1a5bf0d8e43p-54,
+ 0x1.f50765b6e4540p+0, 0x1.9d3e12dd8a18bp-54,
+ 0x1.f7bfdad9cbe13p+0, 0x1.1227697fce57bp-53,
+ 0x1.fa7c1819e90d8p+0, 0x1.74853f3a5931ep-55,
+ 0x1.fd3c22b8f71f1p+0, 0x1.2eb74966579e7p-57
+};
+
+long double
+expl(long double x)
+{
+ union IEEEl2bits u, v;
+ long double fn, q, r, r1, r2, t, t23, t45, twopk, twopkp10000, z;
+ int k, n, n2;
+ uint16_t hx, ix;
+
+ /* Filter out exceptional cases. */
+ u.e = x;
+ hx = u.xbits.expsign;
+ ix = hx & 0x7fff;
+ if (ix >= BIAS + 13) { /* |x| >= 8192 or x is NaN */
+ if (ix == BIAS + LDBL_MAX_EXP) {
+ if (hx & 0x8000 && u.xbits.man == 1ULL << 63)
+ return (0.0L); /* x is -Inf */
+ return (x + x); /* x is +Inf, NaN or unsupported */
+ }
+ if (x > o_threshold.e)
+ return (huge * huge);
+ if (x < u_threshold.e)
+ return (tiny * tiny);
+ } else if (ix < BIAS - 66) { /* |x| < 0x1p-66 */
+ /* includes pseudo-denormals */
+ if (huge + x > 1.0L) /* trigger inexact iff x != 0 */
+ return (1.0L + x);
+ }
+
+ ENTERI();
+
+ /* Reduce x to (k*ln2 + midpoint[n2] + r1 + r2). */
+ /* Use a specialized rint() to get fn. Assume round-to-nearest. */
+ fn = x * INV_L + 0x1.8p63 - 0x1.8p63;
+ r = x - fn * L1 - fn * L2; /* r = r1 + r2 done independently. */
+#if defined(HAVE_EFFICIENT_IRINTL)
+ n = irintl(fn);
+#elif defined(HAVE_EFFICIENT_IRINT)
+ n = irint(fn);
+#else
+ n = (int)fn;
+#endif
+ n2 = (unsigned)n % INTERVALS;
+ k = (n - n2) / INTERVALS;
+ r1 = x - fn * L1;
+ r2 = -fn * L2;
+
+ /* Prepare scale factors. */
+ v.xbits.man = 1ULL << 63;
+ if (k >= LDBL_MIN_EXP) {
+ v.xbits.expsign = BIAS + k;
+ twopk = v.e;
+ } else {
+ v.xbits.expsign = BIAS + k + 10000;
+ twopkp10000 = v.e;
+ }
+
+ /* Evaluate expl(midpoint[n2] + r1 + r2) = s[n2] * expl(r1 + r2). */
+ /* Here q = q(r), not q(r1), since r1 is lopped like L1. */
+ t45 = r * P5 + P4;
+ z = r * r;
+ t23 = r * P3 + P2;
+ q = r2 + z * t23 + z * z * t45 + z * z * z * P6;
+ t = (long double)s[n2].lo + s[n2].hi;
+ t = s[n2].lo + t * (q + r1) + s[n2].hi;
+
+ /* Scale by 2**k. */
+ if (k >= LDBL_MIN_EXP) {
+ if (k == LDBL_MAX_EXP)
+ RETURNI(t * 2.0L * 0x1p16383L);
+ RETURNI(t * twopk);
+ } else {
+ RETURNI(t * twopkp10000 * twom10000);
+ }
+}
diff --git a/lib/msun/man/cexp.3 b/lib/msun/man/cexp.3
index 59bb1cd..97e36c1 100644
--- a/lib/msun/man/cexp.3
+++ b/lib/msun/man/cexp.3
@@ -59,17 +59,17 @@ behaves according to Euler's formula:
.Bd -ragged -offset indent
.Fn cexp "x + I*y"
=
-.Ns ( Sy e Ns ** Ns
+.Po Sy e Ns ** Ns
.Fa x *
-.Em cos Ns ( Ns
-.Fa y Ns )) + ( Ns
+.Em cos Ns Po Ns
+.Fa y Ns Pc Pc + Po Ns
.Sy I
*
.Sy e Ns ** Ns
.Fa x
*
-.Em sin Ns ( Ns
-.Fa y Ns ))
+.Em sin Ns Po Ns
+.Fa y Ns Pc Pc
.Ed
.Pp
Generally speaking, infinities, zeroes and \*(Nas are handled as would
diff --git a/lib/msun/man/exp.3 b/lib/msun/man/exp.3
index b051e5b..5907337 100644
--- a/lib/msun/man/exp.3
+++ b/lib/msun/man/exp.3
@@ -28,13 +28,14 @@
.\" from: @(#)exp.3 6.12 (Berkeley) 7/31/91
.\" $FreeBSD$
.\"
-.Dd January 17, 2008
+.Dd July 10, 2012
.Dt EXP 3
.Os
.Sh NAME
.Nm exp ,
.Nm expf ,
-.\" The sorting error is intentional. exp and expf should be adjacent.
+.Nm expl ,
+.\" The sorting error is intentional. exp, expf, and expl should be adjacent.
.Nm exp2 ,
.Nm exp2f ,
.Nm exp2l ,
@@ -51,6 +52,8 @@
.Fn exp "double x"
.Ft float
.Fn expf "float x"
+.Ft long double
+.Fn expl "long double x"
.Ft double
.Fn exp2 "double x"
.Ft float
@@ -67,9 +70,10 @@
.Fn powf "float x" "float y"
.Sh DESCRIPTION
The
-.Fn exp
-and the
-.Fn expf
+.Fn exp ,
+.Fn expf ,
+and
+.Fn expl
functions compute the base
.Ms e
exponential value of the given argument
diff --git a/lib/msun/man/ieee.3 b/lib/msun/man/ieee.3
index 57e1fcd..5c1c531 100644
--- a/lib/msun/man/ieee.3
+++ b/lib/msun/man/ieee.3
@@ -156,59 +156,60 @@ Wordsize: 32 bits.
.Pp
Precision: 24 significant bits,
roughly like 7 significant decimals.
-.Bd -ragged -offset indent -compact
+.Pp
If x and x' are consecutive positive single-precision
numbers (they differ by 1
.Em ulp ) ,
then
-.Bd -ragged -compact
+.Bl -column "XXX" -compact
5.9e\-08 < 0.5**24 < (x'\-x)/x \(<= 0.5**23 < 1.2e\-07.
-.Ed
-.Ed
+.El
.Pp
.Bl -column "XXX" -compact
Range: Overflow threshold = 2.0**128 = 3.4e38
Underflow threshold = 0.5**126 = 1.2e\-38
.El
-.Bd -ragged -offset indent -compact
+.Pp
Underflowed results round to the nearest
-integer multiple of 0.5**149 = 1.4e\-45.
-.Ed
+integer multiple of
+.Bl -column "XXX" -compact
+0.5**149 = 1.4e\-45.
+.El
.Ed
.Pp
Double-precision:
.Bd -ragged -offset indent -compact
Type name:
.Vt double
-.Bd -ragged -offset indent -compact
-On some architectures,
+.Po On some architectures,
.Vt long double
is the same as
-.Vt double .
-.Ed
+.Vt double
+.Pc
.Pp
Wordsize: 64 bits.
.Pp
Precision: 53 significant bits,
roughly like 16 significant decimals.
-.Bd -ragged -offset indent -compact
+.Pp
If x and x' are consecutive positive double-precision
numbers (they differ by 1
.Em ulp ) ,
then
-.Bd -ragged -compact
+.Bl -column "XXX" -compact
1.1e\-16 < 0.5**53 < (x'\-x)/x \(<= 0.5**52 < 2.3e\-16.
-.Ed
-.Ed
+.El
.Pp
.Bl -column "XXX" -compact
Range: Overflow threshold = 2.0**1024 = 1.8e308
Underflow threshold = 0.5**1022 = 2.2e\-308
.El
-.Bd -ragged -offset indent -compact
+.Pp
Underflowed results round to the nearest
-integer multiple of 0.5**1074 = 4.9e\-324.
-.Ed
+integer multiple of
+.Bl -column "XXX" -compact
+0.5**1074 = 4.9e\-324.
+.El
.Ed
.Pp
Extended-precision:
@@ -221,24 +222,25 @@ Wordsize: 96 bits.
.Pp
Precision: 64 significant bits,
roughly like 19 significant decimals.
-.Bd -ragged -offset indent -compact
+.Pp
If x and x' are consecutive positive extended-precision
numbers (they differ by 1
.Em ulp ) ,
then
-.Bd -ragged -compact
+.Bl -column "XXX" -compact
1.0e\-19 < 0.5**63 < (x'\-x)/x \(<= 0.5**62 < 2.2e\-19.
-.Ed
-.Ed
+.El
.Pp
.Bl -column "XXX" -compact
Range: Overflow threshold = 2.0**16384 = 1.2e4932
Underflow threshold = 0.5**16382 = 3.4e\-4932
.El
-.Bd -ragged -offset indent -compact
+.Pp
Underflowed results round to the nearest
-integer multiple of 0.5**16445 = 5.7e\-4953.
-.Ed
+integer multiple of
+.Bl -column "XXX" -compact
+0.5**16445 = 5.7e\-4953.
+.El
.Ed
.Pp
Quad-extended-precision:
@@ -251,24 +253,25 @@ Wordsize: 128 bits.
.Pp
Precision: 113 significant bits,
roughly like 34 significant decimals.
-.Bd -ragged -offset indent -compact
+.Pp
If x and x' are consecutive positive quad-extended-precision
numbers (they differ by 1
.Em ulp ) ,
then
-.Bd -ragged -compact
+.Bl -column "XXX" -compact
9.6e\-35 < 0.5**113 < (x'\-x)/x \(<= 0.5**112 < 2.0e\-34.
-.Ed
-.Ed
+.El
.Pp
.Bl -column "XXX" -compact
Range: Overflow threshold = 2.0**16384 = 1.2e4932
Underflow threshold = 0.5**16382 = 3.4e\-4932
.El
-.Bd -ragged -offset indent -compact
+.Pp
Underflowed results round to the nearest
-integer multiple of 0.5**16494 = 6.5e\-4966.
-.Ed
+integer multiple of
+.Bl -column "XXX" -compact
+0.5**16494 = 6.5e\-4966.
+.El
.Ed
.Ss Additional Information Regarding Exceptions
For each kind of floating-point exception, IEEE 754
diff --git a/lib/msun/src/e_exp.c b/lib/msun/src/e_exp.c
index b47aef5..e432bc8 100644
--- a/lib/msun/src/e_exp.c
+++ b/lib/msun/src/e_exp.c
@@ -158,3 +158,7 @@ __ieee754_exp(double x) /* default IEEE double exp */
return y*twopk*twom1000;
}
}
+
+#if (LDBL_MANT_DIG == 53)
+__weak_reference(exp, expl);
+#endif
diff --git a/lib/msun/src/e_rem_pio2.c b/lib/msun/src/e_rem_pio2.c
index fde9660..be2630b 100644
--- a/lib/msun/src/e_rem_pio2.c
+++ b/lib/msun/src/e_rem_pio2.c
@@ -48,10 +48,10 @@ pio2_2t = 2.02226624879595063154e-21, /* 0x3BA3198A, 0x2E037073 */
pio2_3 = 2.02226624871116645580e-21, /* 0x3BA3198A, 0x2E000000 */
pio2_3t = 8.47842766036889956997e-32; /* 0x397B839A, 0x252049C1 */
-#ifndef INLINE_REM_PIO2
-extern
+#ifdef INLINE_REM_PIO2
+static __inline __always_inline
#endif
-__inline int
+int
__ieee754_rem_pio2(double x, double *y)
{
double z,w,t,r,fn;
diff --git a/lib/msun/src/e_rem_pio2f.c b/lib/msun/src/e_rem_pio2f.c
index fb608d1..f1ee7a0 100644
--- a/lib/msun/src/e_rem_pio2f.c
+++ b/lib/msun/src/e_rem_pio2f.c
@@ -31,7 +31,7 @@ __FBSDID("$FreeBSD$");
/*
* invpio2: 53 bits of 2/pi
- * pio2_1: first 33 bit of pi/2
+ * pio2_1: first 25 bits of pi/2
* pio2_1t: pi/2 - pio2_1
*/
@@ -40,10 +40,10 @@ invpio2 = 6.36619772367581382433e-01, /* 0x3FE45F30, 0x6DC9C883 */
pio2_1 = 1.57079631090164184570e+00, /* 0x3FF921FB, 0x50000000 */
pio2_1t = 1.58932547735281966916e-08; /* 0x3E5110b4, 0x611A6263 */
-#ifndef INLINE_REM_PIO2F
-extern
+#ifdef INLINE_REM_PIO2F
+static __inline __always_inline
#endif
-__inline int
+int
__ieee754_rem_pio2f(float x, double *y)
{
double w,r,fn;
diff --git a/lib/msun/src/k_cosf.c b/lib/msun/src/k_cosf.c
index 92bce48..f7a2c0a 100644
--- a/lib/msun/src/k_cosf.c
+++ b/lib/msun/src/k_cosf.c
@@ -30,10 +30,10 @@ C1 = 0x155553e1053a42.0p-57, /* 0.0416666233237390631894 */
C2 = -0x16c087e80f1e27.0p-62, /* -0.00138867637746099294692 */
C3 = 0x199342e0ee5069.0p-68; /* 0.0000243904487962774090654 */
-#ifndef INLINE_KERNEL_COSDF
-extern
+#ifdef INLINE_KERNEL_COSDF
+static __inline
#endif
-__inline float
+float
__kernel_cosdf(double x)
{
double r, w, z;
diff --git a/lib/msun/src/k_sinf.c b/lib/msun/src/k_sinf.c
index aa4f268..0841759 100644
--- a/lib/msun/src/k_sinf.c
+++ b/lib/msun/src/k_sinf.c
@@ -29,10 +29,10 @@ S2 = 0x111110896efbb2.0p-59, /* 0.0083333293858894631756 */
S3 = -0x1a00f9e2cae774.0p-65, /* -0.000198393348360966317347 */
S4 = 0x16cd878c3b46a7.0p-71; /* 0.0000027183114939898219064 */
-#ifndef INLINE_KERNEL_SINDF
-extern
+#ifdef INLINE_KERNEL_SINDF
+static __inline
#endif
-__inline float
+float
__kernel_sindf(double x)
{
double r, s, w, z;
diff --git a/lib/msun/src/k_tanf.c b/lib/msun/src/k_tanf.c
index 6b073da..52f1aaa 100644
--- a/lib/msun/src/k_tanf.c
+++ b/lib/msun/src/k_tanf.c
@@ -32,10 +32,10 @@ T[] = {
0x1362b9bf971bcd.0p-59, /* 0.00946564784943673166728 */
};
-#ifndef INLINE_KERNEL_TANDF
-extern
+#ifdef INLINE_KERNEL_TANDF
+static __inline
#endif
-__inline float
+float
__kernel_tandf(double x, int iy)
{
double z,r,w,s,t,u;
diff --git a/lib/msun/src/math.h b/lib/msun/src/math.h
index cf34583..c6cee13 100644
--- a/lib/msun/src/math.h
+++ b/lib/msun/src/math.h
@@ -404,6 +404,7 @@ long double ceill(long double);
long double copysignl(long double, long double) __pure2;
long double cosl(long double);
long double exp2l(long double);
+long double expl(long double);
long double fabsl(long double) __pure2;
long double fdiml(long double, long double);
long double floorl(long double);
@@ -461,7 +462,6 @@ long double atanhl(long double);
long double coshl(long double);
long double erfcl(long double);
long double erfl(long double);
-long double expl(long double);
long double expm1l(long double);
long double lgammal(long double);
long double log10l(long double);
diff --git a/lib/msun/src/math_private.h b/lib/msun/src/math_private.h
index 79280e3..5662df0 100644
--- a/lib/msun/src/math_private.h
+++ b/lib/msun/src/math_private.h
@@ -207,6 +207,17 @@ do { \
(d) = se_u.e; \
} while (0)
+#ifdef __i386__
+/* Long double constants are broken on i386. */
+#define LD80C(m, ex, v) { \
+ .xbits.man = __CONCAT(m, ULL), \
+ .xbits.expsign = (0x3fff + (ex)) | ((v) < 0 ? 0x8000 : 0), \
+}
+#else
+/* The above works on non-i386 too, but we use this to check v. */
+#define LD80C(m, ex, v) { .e = (v), }
+#endif
+
#ifdef FLT_EVAL_METHOD
/*
* Attempt to get strict C99 semantics for assignment with non-C99 compilers.
@@ -217,7 +228,7 @@ do { \
#define STRICT_ASSIGN(type, lval, rval) do { \
volatile type __lval; \
\
- if (sizeof(type) >= sizeof(double)) \
+ if (sizeof(type) >= sizeof(long double)) \
(lval) = (rval); \
else { \
__lval = (rval); \
@@ -225,8 +236,30 @@ do { \
} \
} while (0)
#endif
+#endif /* FLT_EVAL_METHOD */
+
+/* Support switching the mode to FP_PE if necessary. */
+#if defined(__i386__) && !defined(NO_FPSETPREC)
+#define ENTERI() \
+ long double __retval; \
+ fp_prec_t __oprec; \
+ \
+ if ((__oprec = fpgetprec()) != FP_PE) \
+ fpsetprec(FP_PE)
+#define RETURNI(x) do { \
+ __retval = (x); \
+ if (__oprec != FP_PE) \
+ fpsetprec(__oprec); \
+ RETURNF(__retval); \
+} while (0)
+#else
+#define ENTERI(x)
+#define RETURNI(x) RETURNF(x)
#endif
+/* Default return statement if hack*_t() is not used. */
+#define RETURNF(v) return (v)
+
/*
* Common routine to process the arguments to nan(), nanf(), and nanl().
*/
@@ -323,6 +356,18 @@ irint(double x)
#define HAVE_EFFICIENT_IRINT
#endif
+#if defined(__amd64__) || defined(__i386__)
+static __inline int
+irintl(long double x)
+{
+ int n;
+
+ asm("fistl %0" : "=m" (n) : "t" (x));
+ return (n);
+}
+#define HAVE_EFFICIENT_IRINTL
+#endif
+
#endif /* __GNUCLIKE_ASM */
/*
@@ -390,10 +435,9 @@ irint(double x)
int __kernel_rem_pio2(double*,double*,int,int,int);
/* double precision kernel functions */
-#ifdef INLINE_REM_PIO2
-__inline
-#endif
+#ifndef INLINE_REM_PIO2
int __ieee754_rem_pio2(double,double*);
+#endif
double __kernel_sin(double,double,int);
double __kernel_cos(double,double);
double __kernel_tan(double,double,int);
@@ -403,22 +447,18 @@ double complex __ldexp_cexp(double complex,int);
#endif
/* float precision kernel functions */
-#ifdef INLINE_REM_PIO2F
-__inline
-#endif
+#ifndef INLINE_REM_PIO2F
int __ieee754_rem_pio2f(float,double*);
-#ifdef INLINE_KERNEL_SINDF
-__inline
#endif
+#ifndef INLINE_KERNEL_SINDF
float __kernel_sindf(double);
-#ifdef INLINE_KERNEL_COSDF
-__inline
#endif
+#ifndef INLINE_KERNEL_COSDF
float __kernel_cosdf(double);
-#ifdef INLINE_KERNEL_TANDF
-__inline
#endif
+#ifndef INLINE_KERNEL_TANDF
float __kernel_tandf(double,int);
+#endif
float __ldexp_expf(float,int);
#ifdef _COMPLEX_H
float complex __ldexp_cexpf(float complex,int);
diff --git a/lib/msun/src/s_cbrtl.c b/lib/msun/src/s_cbrtl.c
index 23c9184..2236c0f 100644
--- a/lib/msun/src/s_cbrtl.c
+++ b/lib/msun/src/s_cbrtl.c
@@ -18,7 +18,9 @@
__FBSDID("$FreeBSD$");
#include <float.h>
+#ifdef __i386__
#include <ieeefp.h>
+#endif
#include "fpmath.h"
#include "math.h"
@@ -51,23 +53,11 @@ cbrtl(long double x)
if (k == BIAS + LDBL_MAX_EXP)
return (x + x);
-#ifdef __i386__
- fp_prec_t oprec;
-
- oprec = fpgetprec();
- if (oprec != FP_PE)
- fpsetprec(FP_PE);
-#endif
-
+ ENTERI();
if (k == 0) {
/* If x = +-0, then cbrt(x) = +-0. */
- if ((u.bits.manh | u.bits.manl) == 0) {
-#ifdef __i386__
- if (oprec != FP_PE)
- fpsetprec(oprec);
-#endif
- return (x);
- }
+ if ((u.bits.manh | u.bits.manl) == 0)
+ RETURNI(x);
/* Adjust subnormal numbers. */
u.e *= 0x1.0p514;
k = u.bits.exp;
@@ -149,9 +139,5 @@ cbrtl(long double x)
t=t+t*r; /* error <= 0.5 + 0.5/3 + epsilon */
t *= v.e;
-#ifdef __i386__
- if (oprec != FP_PE)
- fpsetprec(oprec);
-#endif
- return (t);
+ RETURNI(t);
}
diff --git a/lib/msun/src/s_cosl.c b/lib/msun/src/s_cosl.c
index 8d43626..22e74cf 100644
--- a/lib/msun/src/s_cosl.c
+++ b/lib/msun/src/s_cosl.c
@@ -33,6 +33,9 @@ __FBSDID("$FreeBSD$");
*/
#include <float.h>
+#ifdef __i386__
+#include <ieeefp.h>
+#endif
#include "math.h"
#include "math_private.h"
@@ -63,9 +66,11 @@ cosl(long double x)
if (z.bits.exp == 32767)
return ((x - x) / (x - x));
+ ENTERI();
+
/* Optimize the case where x is already within range. */
if (z.e < M_PI_4)
- return (__kernel_cosl(z.e, 0));
+ RETURNI(__kernel_cosl(z.e, 0));
e0 = __ieee754_rem_pio2l(x, y);
hi = y[0];
@@ -86,5 +91,5 @@ cosl(long double x)
break;
}
- return (hi);
+ RETURNI(hi);
}
diff --git a/lib/msun/src/s_sinl.c b/lib/msun/src/s_sinl.c
index 919deb9..f454f8f 100644
--- a/lib/msun/src/s_sinl.c
+++ b/lib/msun/src/s_sinl.c
@@ -28,6 +28,9 @@
__FBSDID("$FreeBSD$");
#include <float.h>
+#ifdef __i386__
+#include <ieeefp.h>
+#endif
#include "math.h"
#include "math_private.h"
@@ -59,10 +62,12 @@ sinl(long double x)
if (z.bits.exp == 32767)
return ((x - x) / (x - x));
+ ENTERI();
+
/* Optimize the case where x is already within range. */
if (z.e < M_PI_4) {
hi = __kernel_sinl(z.e, 0, 0);
- return (s ? -hi : hi);
+ RETURNI(s ? -hi : hi);
}
e0 = __ieee754_rem_pio2l(x, y);
@@ -84,5 +89,5 @@ sinl(long double x)
break;
}
- return (hi);
+ RETURNI(hi);
}
diff --git a/lib/msun/src/s_tanl.c b/lib/msun/src/s_tanl.c
index 9562cf8..eadc837 100644
--- a/lib/msun/src/s_tanl.c
+++ b/lib/msun/src/s_tanl.c
@@ -34,6 +34,9 @@ __FBSDID("$FreeBSD$");
*/
#include <float.h>
+#ifdef __i386__
+#include <ieeefp.h>
+#endif
#include "math.h"
#include "math_private.h"
@@ -65,10 +68,12 @@ tanl(long double x)
if (z.bits.exp == 32767)
return ((x - x) / (x - x));
+ ENTERI();
+
/* Optimize the case where x is already within range. */
if (z.e < M_PI_4) {
hi = __kernel_tanl(z.e, 0, 0);
- return (s ? -hi : hi);
+ RETURNI(s ? -hi : hi);
}
e0 = __ieee754_rem_pio2l(x, y);
@@ -86,5 +91,5 @@ tanl(long double x)
break;
}
- return (hi);
+ RETURNI(hi);
}
OpenPOWER on IntegriCloud