aboutsummaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2018-11-14 06:46:44 +0000
committerDimitry Andric <dim@FreeBSD.org>2018-11-14 06:46:44 +0000
commit6149ed01a126d468431ecc4d20d0c00cb0040554 (patch)
tree8ea61e8639bafd9113e9ce899b070db9eedea7ee /sys
parent9b5cb2f639cc6e119a8433e2db6858e4ccab24b4 (diff)
parentfbd5d782096a2ab5a9b212ca7fdcf70050f89f56 (diff)
Notes
Diffstat (limited to 'sys')
-rw-r--r--sys/amd64/amd64/machdep.c1
-rw-r--r--sys/amd64/conf/GENERIC5
-rw-r--r--sys/amd64/conf/MINIMAL5
-rw-r--r--sys/amd64/conf/NOTES5
-rw-r--r--sys/compat/freebsd32/Makefile2
-rw-r--r--sys/compat/freebsd32/capabilities.conf298
-rw-r--r--sys/compat/freebsd32/syscalls.conf2
-rw-r--r--sys/conf/dtb.mk8
-rw-r--r--sys/contrib/libnv/nvpair.c14
-rw-r--r--sys/dev/amdsmn/amdsmn.c23
-rw-r--r--sys/dev/amdtemp/amdtemp.c25
-rw-r--r--sys/dev/cxgbe/t4_netmap.c3
-rw-r--r--sys/dev/nvme/nvme_ns.c6
-rw-r--r--sys/dev/tws/tws.c2
-rw-r--r--sys/dev/tws/tws_cam.c11
-rw-r--r--sys/dev/tws/tws_services.h7
-rw-r--r--sys/dts/Makefile.inc2
-rw-r--r--sys/dts/arm/Makefile2
-rw-r--r--sys/dts/arm/Makefile.inc3
-rw-r--r--sys/dts/arm/overlays/Makefile2
-rw-r--r--sys/dts/arm64/Makefile2
-rw-r--r--sys/dts/arm64/Makefile.inc3
-rw-r--r--sys/dts/arm64/overlays/Makefile2
-rw-r--r--sys/dts/mips/Makefile2
-rw-r--r--sys/dts/powerpc/Makefile2
-rw-r--r--sys/i386/conf/GENERIC5
-rw-r--r--sys/i386/conf/MINIMAL5
-rw-r--r--sys/kern/genoffset.c1
-rw-r--r--sys/kern/kern_environment.c1
-rw-r--r--sys/kern/kern_mutex.c4
-rw-r--r--sys/kern/kern_rmlock.c2
-rw-r--r--sys/kern/kern_rwlock.c6
-rw-r--r--sys/kern/kern_sx.c2
-rw-r--r--sys/kern/kern_thread.c3
-rw-r--r--sys/kern/makesyscalls.sh19
-rw-r--r--sys/kern/subr_blist.c597
-rw-r--r--sys/kern/subr_epoch.c202
-rw-r--r--sys/net/if.c18
-rw-r--r--sys/net/if_var.h2
-rw-r--r--sys/powerpc/conf/GENERIC6414
-rw-r--r--sys/riscv/include/cpu.h4
-rw-r--r--sys/riscv/include/cpufunc.h5
-rw-r--r--sys/riscv/include/riscvreg.h19
-rw-r--r--sys/sys/blist.h8
-rw-r--r--sys/sys/epoch.h56
-rw-r--r--sys/sys/epoch_private.h211
-rw-r--r--sys/sys/proc.h2
-rw-r--r--sys/ufs/ffs/ffs_extern.h2
-rw-r--r--sys/ufs/ffs/ffs_inode.c10
-rw-r--r--sys/ufs/ffs/ffs_snapshot.c4
-rw-r--r--sys/ufs/ffs/ffs_softdep.c16
-rw-r--r--sys/ufs/ffs/ffs_subr.c42
-rw-r--r--sys/ufs/ffs/ffs_vfsops.c20
-rw-r--r--sys/vm/uma_core.c113
-rw-r--r--sys/vm/uma_int.h7
-rw-r--r--sys/x86/include/x86_var.h1
-rw-r--r--sys/x86/x86/identcpu.c20
57 files changed, 722 insertions, 1136 deletions
diff --git a/sys/amd64/amd64/machdep.c b/sys/amd64/amd64/machdep.c
index 6e36ae975239..55db65ffc63c 100644
--- a/sys/amd64/amd64/machdep.c
+++ b/sys/amd64/amd64/machdep.c
@@ -1581,6 +1581,7 @@ hammer_time(u_int64_t modulep, u_int64_t physfree)
identify_cpu1();
identify_hypervisor();
+ identify_cpu_fixup_bsp();
identify_cpu2();
initializecpucache();
diff --git a/sys/amd64/conf/GENERIC b/sys/amd64/conf/GENERIC
index 34fb1e8e4370..fb4754ef4fcc 100644
--- a/sys/amd64/conf/GENERIC
+++ b/sys/amd64/conf/GENERIC
@@ -372,3 +372,8 @@ device vmx # VMware VMXNET3 Ethernet
# Netmap provides direct access to TX/RX rings on supported NICs
device netmap # netmap(4) support
+
+# evdev interface
+options EVDEV_SUPPORT # evdev support in legacy drivers
+device evdev # input event device support
+device uinput # install /dev/uinput cdev
diff --git a/sys/amd64/conf/MINIMAL b/sys/amd64/conf/MINIMAL
index 4a2bb7a0920b..4b0833377a26 100644
--- a/sys/amd64/conf/MINIMAL
+++ b/sys/amd64/conf/MINIMAL
@@ -147,3 +147,8 @@ device bpf # Berkeley packet filter
# NOTE: XENHVM depends on xenpci. They must be added or removed together.
options XENHVM # Xen HVM kernel infrastructure
device xenpci # Xen HVM Hypervisor services driver
+
+# evdev interface
+options EVDEV_SUPPORT # evdev support in legacy drivers
+device evdev # input event device support
+device uinput # install /dev/uinput cdev
diff --git a/sys/amd64/conf/NOTES b/sys/amd64/conf/NOTES
index fdf691e05f86..4367b0358210 100644
--- a/sys/amd64/conf/NOTES
+++ b/sys/amd64/conf/NOTES
@@ -642,6 +642,11 @@ options LINPROCFS
options LINSYSFS
#####################################################################
+# ZFS support
+
+options ZFS
+
+#####################################################################
# VM OPTIONS
# KSTACK_PAGES is the number of memory pages to assign to the kernel
diff --git a/sys/compat/freebsd32/Makefile b/sys/compat/freebsd32/Makefile
index bb933dd4697e..67901e6efcf6 100644
--- a/sys/compat/freebsd32/Makefile
+++ b/sys/compat/freebsd32/Makefile
@@ -11,7 +11,7 @@ all:
sysent: freebsd32_sysent.c freebsd32_syscall.h freebsd32_proto.h freebsd32_systrace_args.c
freebsd32_sysent.c freebsd32_syscalls.c freebsd32_syscall.h freebsd32_proto.h freebsd32_systrace_args.c : \
- ../../kern/makesyscalls.sh syscalls.master syscalls.conf capabilities.conf
+ ../../kern/makesyscalls.sh syscalls.master syscalls.conf ../../kern/capabilities.conf
sh ../../kern/makesyscalls.sh syscalls.master syscalls.conf
clean:
diff --git a/sys/compat/freebsd32/capabilities.conf b/sys/compat/freebsd32/capabilities.conf
deleted file mode 100644
index 12272c4bd251..000000000000
--- a/sys/compat/freebsd32/capabilities.conf
+++ /dev/null
@@ -1,298 +0,0 @@
-##
-## Copyright (c) 2008-2010 Robert N. M. Watson
-## Copyright (c) 2016 The FreeBSD Foundation
-## All rights reserved.
-##
-## This software was developed at the University of Cambridge Computer
-## Laboratory with support from a grant from Google, Inc.
-##
-## Portions of this software were developed by Konstantin Belousov
-## under sponsorship from the FreeBSD Foundation.
-##
-## 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.
-##
-## List of system calls enabled in freebsd32 capability mode, one name
-## per line. See the original list in the sys/kern/capabilities.conf.
-## Position of the compat syscall in this file must be identical to
-## the master, to facilitate comparision and diagnostic.
-##
-## $FreeBSD$
-##
-
-__acl_aclcheck_fd
-__acl_delete_fd
-__acl_get_fd
-__acl_set_fd
-__mac_get_fd
-#__mac_get_pid
-__mac_get_proc
-__mac_set_fd
-__mac_set_proc
-freebsd32___sysctl
-freebsd32__umtx_op
-abort2
-accept
-accept4
-aio_cancel
-freebsd32_aio_error
-freebsd32_aio_fsync
-freebsd32_aio_read
-freebsd32_aio_return
-freebsd32_aio_suspend
-freebsd32_aio_waitcomplete
-freebsd32_aio_write
-#audit
-bindat
-cap_enter
-cap_fcntls_get
-cap_fcntls_limit
-cap_getmode
-freebsd32_cap_ioctls_get
-freebsd32_cap_ioctls_limit
-__cap_rights_get
-cap_rights_limit
-freebsd32_clock_getres
-freebsd32_clock_gettime
-close
-closefrom
-connectat
-#cpuset
-freebsd32_cpuset_getaffinity
-#freebsd32_cpuset_getid
-freebsd32_cpuset_setaffinity
-#freebsd32_cpuset_setid
-dup
-dup2
-extattr_delete_fd
-extattr_get_fd
-extattr_list_fd
-extattr_set_fd
-fchflags
-fchmod
-fchown
-freebsd32_fcntl
-freebsd32_fexecve
-flock
-fork
-fpathconf
-freebsd32_fstat
-freebsd32_fstatat
-freebsd32_getdirentries
-freebsd32_fstatfs
-freebsd32_mknodat
-freebsd32_ftruncate
-freebsd32_lseek
-freebsd32_mmap
-mmap
-freebsd32_pread
-freebsd32_pwrite
-freebsd32_fstat
-fstatfs
-fsync
-ftruncate
-freebsd32_ftruncate
-freebsd32_futimens
-freebsd32_futimes
-getaudit
-getaudit_addr
-getauid
-freebsd32_getcontext
-freebsd32_getdents
-freebsd32_getdirentries
-getdirentries
-getdomainname
-getdtablesize
-getegid
-geteuid
-gethostid
-gethostname
-freebsd32_getitimer
-getgid
-getgroups
-getlogin
-freebsd32_getpagesize
-getpeername
-getpgid
-getpgrp
-getpid
-getppid
-getpriority
-getrandom
-getresgid
-getresuid
-getrlimit
-freebsd32_getrusage
-getsid
-getsockname
-getsockopt
-freebsd32_gettimeofday
-getuid
-freebsd32_ioctl
-issetugid
-freebsd32_kevent
-kill
-freebsd32_kmq_notify
-freebsd32_kmq_setattr
-freebsd32_kmq_timedreceive
-freebsd32_kmq_timedsend
-kqueue
-freebsd32_ktimer_create
-ktimer_delete
-ktimer_getoverrun
-freebsd32_ktimer_gettime
-freebsd32_ktimer_settime
-#ktrace
-freebsd32_lio_listio
-listen
-freebsd32_lseek
-madvise
-mincore
-minherit
-mlock
-mlockall
-freebsd32_mmap
-freebsd32_mprotect
-msync
-munlock
-munlockall
-munmap
-freebsd32_nanosleep
-ntp_gettime
-freebsd6_freebsd32_aio_read
-freebsd6_freebsd32_aio_write
-break
-freebsd6_freebsd32_lio_listio
-chflagsat
-faccessat
-fchmodat
-fchownat
-freebsd32_fstatat
-freebsd32_futimesat
-linkat
-mkdirat
-mkfifoat
-mknodat
-openat
-readlinkat
-renameat
-symlinkat
-unlinkat
-freebsd32_utimensat
-pdfork
-pdgetpid
-pdkill
-#pdwait4 # not yet implemented
-freebsd32_pipe
-pipe2
-poll
-freebsd32_ppoll
-freebsd32_posix_fallocate
-freebsd32_pread
-freebsd32_preadv
-profil
-#ptrace
-freebsd32_pwrite
-freebsd32_pwritev
-read
-freebsd32_readv
-freebsd6_freebsd32_recv
-freebsd32_recvfrom
-freebsd32_recvmsg
-rtprio
-rtprio_thread
-sbrk
-sched_get_priority_max
-sched_get_priority_min
-sched_getparam
-sched_getscheduler
-freebsd32_sched_rr_get_interval
-sched_setparam
-sched_setscheduler
-sched_yield
-sctp_generic_recvmsg
-sctp_generic_sendmsg
-sctp_generic_sendmsg_iov
-sctp_peeloff
-freebsd32_pselect
-freebsd32_select
-freebsd6_freebsd32_send
-freebsd32_sendfile
-freebsd32_sendmsg
-sendto
-setaudit
-setaudit_addr
-setauid
-freebsd32_setcontext
-setegid
-seteuid
-setgid
-freebsd32_setitimer
-setpriority
-setregid
-setresgid
-setresuid
-setreuid
-setrlimit
-setsid
-setsockopt
-setuid
-shm_open
-shutdown
-freebsd32_sigaction
-freebsd32_sigaltstack
-freebsd32_sigblock
-freebsd32_sigpending
-sigpending
-freebsd32_sigprocmask
-sigprocmask
-freebsd32_sigqueue
-sigqueue
-freebsd32_sigreturn
-freebsd32_sigsetmask
-freebsd32_sigstack
-freebsd32_sigsuspend
-sigsuspend
-freebsd32_sigtimedwait
-freebsd32_sigvec
-freebsd32_sigwaitinfo
-sigwait
-socket
-socketpair
-sstk
-sync
-sys_exit
-freebsd32_sysarch
-thr_create
-thr_exit
-thr_kill
-#thr_kill2
-freebsd32_thr_new
-thr_self
-thr_set_name
-freebsd32_thr_suspend
-thr_wake
-umask
-utrace
-uuidgen
-write
-freebsd32_writev
-yield
diff --git a/sys/compat/freebsd32/syscalls.conf b/sys/compat/freebsd32/syscalls.conf
index 3715400fff8b..0b3d59f2fcf3 100644
--- a/sys/compat/freebsd32/syscalls.conf
+++ b/sys/compat/freebsd32/syscalls.conf
@@ -9,3 +9,5 @@ syscallprefix="FREEBSD32_SYS_"
switchname="freebsd32_sysent"
namesname="freebsd32_syscallnames"
systrace="freebsd32_systrace_args.c"
+abi_func_prefix="freebsd32_"
+capabilities_conf="../../kern/capabilities.conf"
diff --git a/sys/conf/dtb.mk b/sys/conf/dtb.mk
index f072bd200557..003ecc62ddb6 100644
--- a/sys/conf/dtb.mk
+++ b/sys/conf/dtb.mk
@@ -55,21 +55,21 @@ DTBO=${DTSO:R:S/$/.dtbo/}
all: ${DTB} ${DTBO}
.if defined(DTS)
-.export DTC
+.export DTC ECHO
.for _dts in ${DTS}
${_dts:R:S/$/.dtb/}: ${_dts} ${OP_META}
@${ECHO} Generating ${.TARGET} from ${_dts}
- @env ECHO=${ECHO} ${SYSDIR}/tools/fdt/make_dtb.sh ${SYSDIR} ${_dts} ${.OBJDIR}
+ @${SYSDIR}/tools/fdt/make_dtb.sh ${SYSDIR} ${_dts} ${.OBJDIR}
CLEANFILES+=${_dts:R:S/$/.dtb/}
.endfor
.endif
.if defined(DTSO)
-.export DTC
+.export DTC ECHO
.for _dtso in ${DTSO}
${_dtso:R:S/$/.dtbo/}: ${_dtso} ${OP_META}
@${ECHO} Generating ${.TARGET} from ${_dtso}
- @env ECHO=${ECHO} ${SYSDIR}/tools/fdt/make_dtbo.sh ${SYSDIR} overlays/${_dtso} ${.OBJDIR}
+ @${SYSDIR}/tools/fdt/make_dtbo.sh ${SYSDIR} overlays/${_dtso} ${.OBJDIR}
CLEANFILES+=${_dtso:R:S/$/.dtbo/}
.endfor
.endif
diff --git a/sys/contrib/libnv/nvpair.c b/sys/contrib/libnv/nvpair.c
index fc2350d9f0db..23038c5c5b71 100644
--- a/sys/contrib/libnv/nvpair.c
+++ b/sys/contrib/libnv/nvpair.c
@@ -1276,11 +1276,6 @@ nvpair_create_descriptor(const char *name, int value)
{
nvpair_t *nvp;
- if (value < 0 || !fd_is_valid(value)) {
- ERRNO_SET(EBADF);
- return (NULL);
- }
-
value = fcntl(value, F_DUPFD_CLOEXEC, 0);
if (value < 0)
return (NULL);
@@ -1517,11 +1512,6 @@ nvpair_create_descriptor_array(const char *name, const int *value,
if (value[ii] == -1) {
fds[ii] = -1;
} else {
- if (!fd_is_valid(value[ii])) {
- ERRNO_SET(EBADF);
- goto fail;
- }
-
fds[ii] = fcntl(value[ii], F_DUPFD_CLOEXEC, 0);
if (fds[ii] == -1)
goto fail;
@@ -2035,10 +2025,6 @@ nvpair_append_descriptor_array(nvpair_t *nvp, const int value)
NVPAIR_ASSERT(nvp);
PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR_ARRAY);
- if (value < 0 || !fd_is_valid(value)) {
- ERRNO_SET(EBADF);
- return -1;
- }
fd = fcntl(value, F_DUPFD_CLOEXEC, 0);
if (fd == -1) {
return (-1);
diff --git a/sys/dev/amdsmn/amdsmn.c b/sys/dev/amdsmn/amdsmn.c
index 17792dd922cd..245c375ac202 100644
--- a/sys/dev/amdsmn/amdsmn.c
+++ b/sys/dev/amdsmn/amdsmn.c
@@ -42,6 +42,7 @@ __FBSDID("$FreeBSD$");
#include <sys/systm.h>
#include <machine/cpufunc.h>
+#include <machine/cputypes.h>
#include <machine/md_var.h>
#include <machine/specialreg.h>
@@ -53,14 +54,21 @@ __FBSDID("$FreeBSD$");
#define SMN_ADDR_REG 0x60
#define SMN_DATA_REG 0x64
+#define PCI_DEVICE_ID_AMD_17H_ROOT 0x1450
+#define PCI_DEVICE_ID_AMD_17H_ROOT_DF_F3 0x1463
+#define PCI_DEVICE_ID_AMD_17H_M10H_ROOT 0x15d0
+#define PCI_DEVICE_ID_AMD_17H_M10H_ROOT_DF_F3 0x15eb
+
struct amdsmn_softc {
struct mtx smn_lock;
};
static struct pciid {
- uint32_t device_id;
+ uint16_t amdsmn_vendorid;
+ uint16_t amdsmn_deviceid;
} amdsmn_ids[] = {
- { 0x14501022 },
+ { CPU_VENDOR_AMD, PCI_DEVICE_ID_AMD_17H_ROOT },
+ { CPU_VENDOR_AMD, PCI_DEVICE_ID_AMD_17H_M10H_ROOT },
};
/*
@@ -89,18 +97,21 @@ static driver_t amdsmn_driver = {
static devclass_t amdsmn_devclass;
DRIVER_MODULE(amdsmn, hostb, amdsmn_driver, amdsmn_devclass, NULL, NULL);
MODULE_VERSION(amdsmn, 1);
-MODULE_PNP_INFO("W32:vendor/device", pci, amdsmn, amdsmn_ids,
+MODULE_PNP_INFO("U16:vendor;U16:device", pci, amdsmn, amdsmn_ids,
nitems(amdsmn_ids));
static bool
amdsmn_match(device_t parent)
{
- uint32_t devid;
+ uint16_t vendor, device;
size_t i;
- devid = pci_get_devid(parent);
+ vendor = pci_get_vendor(parent);
+ device = pci_get_device(parent);
+
for (i = 0; i < nitems(amdsmn_ids); i++)
- if (amdsmn_ids[i].device_id == devid)
+ if (vendor == amdsmn_ids[i].amdsmn_vendorid &&
+ device == amdsmn_ids[i].amdsmn_deviceid)
return (true);
return (false);
}
diff --git a/sys/dev/amdtemp/amdtemp.c b/sys/dev/amdtemp/amdtemp.c
index 2463212c25f5..2c7afcd0c10b 100644
--- a/sys/dev/amdtemp/amdtemp.c
+++ b/sys/dev/amdtemp/amdtemp.c
@@ -86,7 +86,10 @@ struct amdtemp_softc {
#define DEVICEID_AMD_MISC16 0x1533
#define DEVICEID_AMD_MISC16_M30H 0x1583
#define DEVICEID_AMD_MISC17 0x141d
-#define DEVICEID_AMD_HOSTB17H 0x1450
+#define DEVICEID_AMD_HOSTB17H_ROOT 0x1450
+#define DEVICEID_AMD_HOSTB17H_DF_F3 0x1463
+#define DEVICEID_AMD_HOSTB17H_M10H_ROOT 0x15d0
+#define DEVICEID_AMD_HOSTB17H_M10H_DF_F3 0x15eb
static struct amdtemp_product {
uint16_t amdtemp_vendorid;
@@ -101,7 +104,8 @@ static struct amdtemp_product {
{ VENDORID_AMD, DEVICEID_AMD_MISC16 },
{ VENDORID_AMD, DEVICEID_AMD_MISC16_M30H },
{ VENDORID_AMD, DEVICEID_AMD_MISC17 },
- { VENDORID_AMD, DEVICEID_AMD_HOSTB17H },
+ { VENDORID_AMD, DEVICEID_AMD_HOSTB17H_ROOT },
+ { VENDORID_AMD, DEVICEID_AMD_HOSTB17H_M10H_ROOT },
};
/*
@@ -111,8 +115,15 @@ static struct amdtemp_product {
/*
* Reported Temperature, Family 17h
+ *
+ * According to AMD OSRR for 17H, section 4.2.1, bits 31-21 of this register
+ * provide the current temp. bit 19, when clear, means the temp is reported in
+ * a range 0.."225C" (probable typo for 255C), and when set changes the range
+ * to -49..206C.
*/
-#define AMDTEMP_17H_CUR_TMP 0x59800
+#define AMDTEMP_17H_CUR_TMP 0x59800
+#define AMDTEMP_17H_CUR_TMP_RANGE_SEL (1 << 19)
+#define AMDTEMP_17H_CUR_TMP_RANGE_OFF 490
/*
* Thermaltrip Status Register (Family 0Fh only)
@@ -591,13 +602,15 @@ static int32_t
amdtemp_gettemp17h(device_t dev, amdsensor_t sensor)
{
struct amdtemp_softc *sc = device_get_softc(dev);
- uint32_t temp;
+ uint32_t temp, val;
int error;
- error = amdsmn_read(sc->sc_smn, AMDTEMP_17H_CUR_TMP, &temp);
+ error = amdsmn_read(sc->sc_smn, AMDTEMP_17H_CUR_TMP, &val);
KASSERT(error == 0, ("amdsmn_read"));
- temp = ((temp >> 21) & 0x7ff) * 5 / 4;
+ temp = ((val >> 21) & 0x7ff) * 5 / 4;
+ if ((val & AMDTEMP_17H_CUR_TMP_RANGE_SEL) != 0)
+ temp -= AMDTEMP_17H_CUR_TMP_RANGE_OFF;
temp += AMDTEMP_ZERO_C_TO_K + sc->sc_offset * 10;
return (temp);
diff --git a/sys/dev/cxgbe/t4_netmap.c b/sys/dev/cxgbe/t4_netmap.c
index adcd82034277..a27d54ec07f6 100644
--- a/sys/dev/cxgbe/t4_netmap.c
+++ b/sys/dev/cxgbe/t4_netmap.c
@@ -492,6 +492,9 @@ cxgbe_netmap_off(struct adapter *sc, struct vi_info *vi, struct ifnet *ifp,
ASSERT_SYNCHRONIZED_OP(sc);
+ if (!nm_netmap_on(na))
+ return (0);
+
if ((vi->flags & VI_INIT_DONE) == 0)
return (0);
diff --git a/sys/dev/nvme/nvme_ns.c b/sys/dev/nvme/nvme_ns.c
index fd95a29ee180..d701b473b00c 100644
--- a/sys/dev/nvme/nvme_ns.c
+++ b/sys/dev/nvme/nvme_ns.c
@@ -535,11 +535,11 @@ nvme_ns_construct(struct nvme_namespace *ns, uint32_t id,
if (!mtx_initialized(&ns->lock))
mtx_init(&ns->lock, "nvme ns lock", NULL, MTX_DEF);
- status.done = FALSE;
+ status.done = 0;
nvme_ctrlr_cmd_identify_namespace(ctrlr, id, &ns->data,
nvme_completion_poll_cb, &status);
- while (status.done == FALSE)
- DELAY(5);
+ while (!atomic_load_acq_int(&status.done))
+ pause("nvme", 1);
if (nvme_completion_is_error(&status.cpl)) {
nvme_printf(ctrlr, "nvme_identify_namespace failed\n");
return (ENXIO);
diff --git a/sys/dev/tws/tws.c b/sys/dev/tws/tws.c
index 6b89966e7033..6cb814533ac6 100644
--- a/sys/dev/tws/tws.c
+++ b/sys/dev/tws/tws.c
@@ -445,9 +445,7 @@ tws_setup_intr(struct tws_softc *sc, int irqs)
if (!(sc->intr_handle[i])) {
if ((error = bus_setup_intr(sc->tws_dev, sc->irq_res[i],
INTR_TYPE_CAM | INTR_MPSAFE,
-#if (__FreeBSD_version >= 700000)
NULL,
-#endif
tws_intr, sc, &sc->intr_handle[i]))) {
tws_log(sc, SETUP_INTR_RES);
return(FAILURE);
diff --git a/sys/dev/tws/tws_cam.c b/sys/dev/tws/tws_cam.c
index f948af092819..a8d75cc8fc20 100644
--- a/sys/dev/tws/tws_cam.c
+++ b/sys/dev/tws/tws_cam.c
@@ -160,9 +160,7 @@ tws_cam_attach(struct tws_softc *sc)
*/
sc->sim = cam_sim_alloc(tws_action, tws_poll, "tws", sc,
device_get_unit(sc->tws_dev),
-#if (__FreeBSD_version >= 700000)
&sc->sim_lock,
-#endif
tws_cam_depth, 1, devq);
/* 1, 1, devq); */
if (sc->sim == NULL) {
@@ -172,9 +170,7 @@ tws_cam_attach(struct tws_softc *sc)
/* Register the bus. */
mtx_lock(&sc->sim_lock);
if (xpt_bus_register(sc->sim,
-#if (__FreeBSD_version >= 700000)
sc->tws_dev,
-#endif
0) != CAM_SUCCESS) {
cam_sim_free(sc->sim, TRUE); /* passing true will free the devq */
sc->sim = NULL; /* so cam_detach will not try to free it */
@@ -269,7 +265,6 @@ tws_action(struct cam_sim *sim, union ccb *ccb)
{
TWS_TRACE_DEBUG(sc, "get tran settings", sim, ccb);
-#if (__FreeBSD_version >= 700000 )
ccb->cts.protocol = PROTO_SCSI;
ccb->cts.protocol_version = SCSI_REV_2;
ccb->cts.transport = XPORT_SPI;
@@ -279,10 +274,6 @@ tws_action(struct cam_sim *sim, union ccb *ccb)
ccb->cts.xport_specific.spi.flags = CTS_SPI_FLAGS_DISC_ENB;
ccb->cts.proto_specific.scsi.valid = CTS_SCSI_VALID_TQ;
ccb->cts.proto_specific.scsi.flags = CTS_SCSI_FLAGS_TAG_ENB;
-#else
- ccb->cts.valid = (CCB_TRANS_DISC_VALID | CCB_TRANS_TQ_VALID);
- ccb->cts.flags &= ~(CCB_TRANS_DISC_ENB | CCB_TRANS_TAG_ENB);
-#endif
ccb->ccb_h.status = CAM_REQ_CMP;
xpt_done(ccb);
@@ -314,13 +305,11 @@ tws_action(struct cam_sim *sim, union ccb *ccb)
strlcpy(ccb->cpi.sim_vid, "FreeBSD", SIM_IDLEN);
strlcpy(ccb->cpi.hba_vid, "3ware", HBA_IDLEN);
strlcpy(ccb->cpi.dev_name, cam_sim_name(sim), DEV_IDLEN);
-#if (__FreeBSD_version >= 700000 )
ccb->cpi.transport = XPORT_SPI;
ccb->cpi.transport_version = 2;
ccb->cpi.protocol = PROTO_SCSI;
ccb->cpi.protocol_version = SCSI_REV_2;
ccb->cpi.maxio = TWS_MAX_IO_SIZE;
-#endif
ccb->ccb_h.status = CAM_REQ_CMP;
xpt_done(ccb);
diff --git a/sys/dev/tws/tws_services.h b/sys/dev/tws/tws_services.h
index 9fa3c3799994..22d0b50207dc 100644
--- a/sys/dev/tws/tws_services.h
+++ b/sys/dev/tws/tws_services.h
@@ -131,12 +131,5 @@ struct error_desc {
/* ------------------------ */
-#if (__FreeBSD_version >= 700000)
#include <sys/clock.h>
#define TWS_LOCAL_TIME (time_second - utc_offset())
-#else
-#include <machine/clock.h>
-#define TWS_LOCAL_TIME (time_second - (tz_minuteswest * 60) - \
- (wall_cmos_clock ? adjkerntz : 0))
-#endif
-
diff --git a/sys/dts/Makefile.inc b/sys/dts/Makefile.inc
index 2161751dc237..bb6fef4bbd20 100644
--- a/sys/dts/Makefile.inc
+++ b/sys/dts/Makefile.inc
@@ -5,9 +5,9 @@ SYSDIR?=${SRCTOP}/sys
test-dts:
.for dts in ${DTS}
@env MACHINE=`basename ${.CURDIR}` ${SYSDIR}/tools/fdt/make_dtb.sh ${SYSDIR} ${dts} /tmp
+.endfor
test-dtso:
.for dtso in ${DTSO}
@env MACHINE=`basename ${.CURDIR}` ${SYSDIR}/tools/fdt/make_dtbo.sh ${SYSDIR} ${dtso} /tmp
-
.endfor
diff --git a/sys/dts/arm/Makefile b/sys/dts/arm/Makefile
index 03d156d94770..855f8847d514 100644
--- a/sys/dts/arm/Makefile
+++ b/sys/dts/arm/Makefile
@@ -1,6 +1,6 @@
# $FreeBSD$
-DTS!=ls *.dts
+DTS!=ls ${.CURDIR}/*.dts
all: test-dts
diff --git a/sys/dts/arm/Makefile.inc b/sys/dts/arm/Makefile.inc
new file mode 100644
index 000000000000..265f86d1ed55
--- /dev/null
+++ b/sys/dts/arm/Makefile.inc
@@ -0,0 +1,3 @@
+# $FreeBSD$
+
+.include "../Makefile.inc"
diff --git a/sys/dts/arm/overlays/Makefile b/sys/dts/arm/overlays/Makefile
index aff6f3d459bc..cfc655929ef3 100644
--- a/sys/dts/arm/overlays/Makefile
+++ b/sys/dts/arm/overlays/Makefile
@@ -1,6 +1,6 @@
# $FreeBSD$
-DTSO!=ls *.dtso
+DTSO!=ls ${.CURDIR}/*.dtso
all: test-dtso
diff --git a/sys/dts/arm64/Makefile b/sys/dts/arm64/Makefile
index 03d156d94770..855f8847d514 100644
--- a/sys/dts/arm64/Makefile
+++ b/sys/dts/arm64/Makefile
@@ -1,6 +1,6 @@
# $FreeBSD$
-DTS!=ls *.dts
+DTS!=ls ${.CURDIR}/*.dts
all: test-dts
diff --git a/sys/dts/arm64/Makefile.inc b/sys/dts/arm64/Makefile.inc
new file mode 100644
index 000000000000..265f86d1ed55
--- /dev/null
+++ b/sys/dts/arm64/Makefile.inc
@@ -0,0 +1,3 @@
+# $FreeBSD$
+
+.include "../Makefile.inc"
diff --git a/sys/dts/arm64/overlays/Makefile b/sys/dts/arm64/overlays/Makefile
index aff6f3d459bc..cfc655929ef3 100644
--- a/sys/dts/arm64/overlays/Makefile
+++ b/sys/dts/arm64/overlays/Makefile
@@ -1,6 +1,6 @@
# $FreeBSD$
-DTSO!=ls *.dtso
+DTSO!=ls ${.CURDIR}/*.dtso
all: test-dtso
diff --git a/sys/dts/mips/Makefile b/sys/dts/mips/Makefile
index 03d156d94770..855f8847d514 100644
--- a/sys/dts/mips/Makefile
+++ b/sys/dts/mips/Makefile
@@ -1,6 +1,6 @@
# $FreeBSD$
-DTS!=ls *.dts
+DTS!=ls ${.CURDIR}/*.dts
all: test-dts
diff --git a/sys/dts/powerpc/Makefile b/sys/dts/powerpc/Makefile
index 03d156d94770..855f8847d514 100644
--- a/sys/dts/powerpc/Makefile
+++ b/sys/dts/powerpc/Makefile
@@ -1,6 +1,6 @@
# $FreeBSD$
-DTS!=ls *.dts
+DTS!=ls ${.CURDIR}/*.dts
all: test-dts
diff --git a/sys/i386/conf/GENERIC b/sys/i386/conf/GENERIC
index e3f0a62d7e00..46e6a599fb40 100644
--- a/sys/i386/conf/GENERIC
+++ b/sys/i386/conf/GENERIC
@@ -366,3 +366,8 @@ device xenpci # Xen HVM Hypervisor services driver
# VMware support
device vmx # VMware VMXNET3 Ethernet
+
+# evdev interface
+options EVDEV_SUPPORT # evdev support in legacy drivers
+device evdev # input event device support
+device uinput # install /dev/uinput cdev
diff --git a/sys/i386/conf/MINIMAL b/sys/i386/conf/MINIMAL
index 60869f93e804..6e578223ba55 100644
--- a/sys/i386/conf/MINIMAL
+++ b/sys/i386/conf/MINIMAL
@@ -148,3 +148,8 @@ device bpf # Berkeley packet filter
# NOTE: XENHVM depends on xenpci. They must be added or removed together.
options XENHVM # Xen HVM kernel infrastructure
device xenpci # Xen HVM Hypervisor services driver
+
+# evdev interface
+options EVDEV_SUPPORT # evdev support in legacy drivers
+device evdev # input event device support
+device uinput # install /dev/uinput cdev
diff --git a/sys/kern/genoffset.c b/sys/kern/genoffset.c
index 4a1e12a1d072..aadb909e943c 100644
--- a/sys/kern/genoffset.c
+++ b/sys/kern/genoffset.c
@@ -36,7 +36,6 @@ __FBSDID("$FreeBSD$");
#include <sys/assym.h>
#include <sys/proc.h>
-OFFSYM(td_pre_epoch_prio, thread, u_char);
OFFSYM(td_priority, thread, u_char);
OFFSYM(td_epochnest, thread, u_char);
OFFSYM(td_critnest, thread, u_int);
diff --git a/sys/kern/kern_environment.c b/sys/kern/kern_environment.c
index b8eebc217721..a2480c3d689e 100644
--- a/sys/kern/kern_environment.c
+++ b/sys/kern/kern_environment.c
@@ -249,6 +249,7 @@ init_static_kenv(char *buf, size_t len)
{
char *eval;
+ KASSERT(!dynamic_kenv, ("kenv: dynamic_kenv already initialized"));
/*
* Give the static environment a chance to disable the loader(8)
* environment first. This is done with loader_env.disabled=1.
diff --git a/sys/kern/kern_mutex.c b/sys/kern/kern_mutex.c
index 65c2e299bbc7..a35cd3b834fb 100644
--- a/sys/kern/kern_mutex.c
+++ b/sys/kern/kern_mutex.c
@@ -486,7 +486,7 @@ __mtx_lock_sleep(volatile uintptr_t *c, uintptr_t v)
int64_t all_time = 0;
#endif
#if defined(KDTRACE_HOOKS) || defined(LOCK_PROFILING)
- int doing_lockprof;
+ int doing_lockprof = 0;
#endif
td = curthread;
@@ -690,7 +690,7 @@ _mtx_lock_spin_cookie(volatile uintptr_t *c, uintptr_t v)
int64_t spin_time = 0;
#endif
#if defined(KDTRACE_HOOKS) || defined(LOCK_PROFILING)
- int doing_lockprof;
+ int doing_lockprof = 0;
#endif
tid = (uintptr_t)curthread;
diff --git a/sys/kern/kern_rmlock.c b/sys/kern/kern_rmlock.c
index 80f54006b693..5cb18fbfa582 100644
--- a/sys/kern/kern_rmlock.c
+++ b/sys/kern/kern_rmlock.c
@@ -742,7 +742,7 @@ _rm_assert(const struct rmlock *rm, int what, const char *file, int line)
{
int count;
- if (panicstr != NULL)
+ if (SCHEDULER_STOPPED())
return;
switch (what) {
case RA_LOCKED:
diff --git a/sys/kern/kern_rwlock.c b/sys/kern/kern_rwlock.c
index 9ec967b94192..2d3342e497d1 100644
--- a/sys/kern/kern_rwlock.c
+++ b/sys/kern/kern_rwlock.c
@@ -445,7 +445,7 @@ __rw_rlock_hard(struct rwlock *rw, struct thread *td, uintptr_t v
int64_t all_time = 0;
#endif
#if defined(KDTRACE_HOOKS) || defined(LOCK_PROFILING)
- uintptr_t state;
+ uintptr_t state = 0;
int doing_lockprof = 0;
#endif
@@ -913,7 +913,7 @@ __rw_wlock_hard(volatile uintptr_t *c, uintptr_t v LOCK_FILE_LINE_ARG_DEF)
int64_t all_time = 0;
#endif
#if defined(KDTRACE_HOOKS) || defined(LOCK_PROFILING)
- uintptr_t state;
+ uintptr_t state = 0;
int doing_lockprof = 0;
#endif
int extra_work = 0;
@@ -1439,7 +1439,7 @@ __rw_assert(const volatile uintptr_t *c, int what, const char *file, int line)
{
const struct rwlock *rw;
- if (panicstr != NULL)
+ if (SCHEDULER_STOPPED())
return;
rw = rwlock2rw(c);
diff --git a/sys/kern/kern_sx.c b/sys/kern/kern_sx.c
index c1ebfb2f715a..600a3d03558a 100644
--- a/sys/kern/kern_sx.c
+++ b/sys/kern/kern_sx.c
@@ -1416,7 +1416,7 @@ _sx_assert(const struct sx *sx, int what, const char *file, int line)
int slocked = 0;
#endif
- if (panicstr != NULL)
+ if (SCHEDULER_STOPPED())
return;
switch (what) {
case SA_SLOCKED:
diff --git a/sys/kern/kern_thread.c b/sys/kern/kern_thread.c
index b60c2d5b40ef..ee456fc6920e 100644
--- a/sys/kern/kern_thread.c
+++ b/sys/kern/kern_thread.c
@@ -40,6 +40,7 @@ __FBSDID("$FreeBSD$");
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/proc.h>
+#include <sys/epoch.h>
#include <sys/rangelock.h>
#include <sys/resourcevar.h>
#include <sys/sdt.h>
@@ -272,6 +273,7 @@ thread_init(void *mem, int size, int flags)
td->td_rlqe = NULL;
EVENTHANDLER_DIRECT_INVOKE(thread_init, td);
umtx_thread_init(td);
+ epoch_thread_init(td);
td->td_kstack = 0;
td->td_sel = NULL;
return (0);
@@ -291,6 +293,7 @@ thread_fini(void *mem, int size)
turnstile_free(td->td_turnstile);
sleepq_free(td->td_sleepqueue);
umtx_thread_fini(td);
+ epoch_thread_fini(td);
seltdfini(td);
}
diff --git a/sys/kern/makesyscalls.sh b/sys/kern/makesyscalls.sh
index 4030ed321693..0e95a79c7bad 100644
--- a/sys/kern/makesyscalls.sh
+++ b/sys/kern/makesyscalls.sh
@@ -45,13 +45,7 @@ sysarg="sysarg.switch.$$"
sysprotoend="sysprotoend.$$"
systracetmp="systrace.$$"
systraceret="systraceret.$$"
-
-if [ -r capabilities.conf ]; then
- capenabled=`egrep -v '^#|^$' capabilities.conf`
- capenabled=`echo $capenabled | sed 's/ /,/g'`
-else
- capenabled=""
-fi
+capabilities_conf="capabilities.conf"
trap "rm $sysaue $sysdcl $syscompat $syscompatdcl $syscompat4 $syscompat4dcl $syscompat6 $syscompat6dcl $syscompat7 $syscompat7dcl $syscompat10 $syscompat10dcl $syscompat11 $syscompat11dcl $sysent $sysinc $sysarg $sysprotoend $systracetmp $systraceret" 0
@@ -67,6 +61,13 @@ if [ -n "$2" ]; then
. $2
fi
+if [ -r $capabilities_conf ]; then
+ capenabled=`egrep -v '^#|^$' $capabilities_conf`
+ capenabled=`echo $capenabled | sed 's/ /,/g'`
+else
+ capenabled=""
+fi
+
sed -e '
# FreeBSD ID, includes, comments, and blank lines
/.*\$FreeBSD/b done_joining
@@ -137,6 +138,7 @@ sed -e '
switchname = \"$switchname\"
namesname = \"$namesname\"
infile = \"$1\"
+ abi_func_prefix = \"$abi_func_prefix\"
capenabled_string = \"$capenabled\"
"'
@@ -381,7 +383,8 @@ sed -e '
# from it.
#
for (cap in capenabled) {
- if (funcname == capenabled[cap]) {
+ if (funcname == capenabled[cap] ||
+ funcname == abi_func_prefix capenabled[cap]) {
flags = "SYF_CAPENABLED";
break;
}
diff --git a/sys/kern/subr_blist.c b/sys/kern/subr_blist.c
index db7df6932633..0e5156c5053c 100644
--- a/sys/kern/subr_blist.c
+++ b/sys/kern/subr_blist.c
@@ -46,11 +46,11 @@
* upper bound on a potential allocation, but not necessarily a tight upper
* bound.
*
- * The radix tree also implements two collapsed states for meta nodes:
- * the ALL-ALLOCATED state and the ALL-FREE state. If a meta node is
- * in either of these two states, all information contained underneath
- * the node is considered stale. These states are used to optimize
- * allocation and freeing operations.
+ * The bitmap field in each node directs the search for available blocks.
+ * For a leaf node, a bit is set if the corresponding block is free. For a
+ * meta node, a bit is set if the corresponding subtree contains a free
+ * block somewhere within it. The search at a meta node considers only
+ * children of that node that represent a range that includes a free block.
*
* The hinting greatly increases code efficiency for allocations while
* the general radix structure optimizes both allocations and frees. The
@@ -59,19 +59,19 @@
*
* The blist code wires all necessary memory at creation time. Neither
* allocations nor frees require interaction with the memory subsystem.
- * The non-blocking features of the blist code are used in the swap code
- * (vm/swap_pager.c).
+ * The non-blocking nature of allocations and frees is required by swap
+ * code (vm/swap_pager.c).
*
- * LAYOUT: The radix tree is laid out recursively using a
- * linear array. Each meta node is immediately followed (laid out
- * sequentially in memory) by BLIST_META_RADIX lower level nodes. This
- * is a recursive structure but one that can be easily scanned through
- * a very simple 'skip' calculation. In order to support large radixes,
- * portions of the tree may reside outside our memory allocation. We
- * handle this with an early-termination optimization (when bighint is
- * set to -1) on the scan. The memory allocation is only large enough
- * to cover the number of blocks requested at creation time even if it
- * must be encompassed in larger root-node radix.
+ * LAYOUT: The radix tree is laid out recursively using a linear array.
+ * Each meta node is immediately followed (laid out sequentially in
+ * memory) by BLIST_META_RADIX lower level nodes. This is a recursive
+ * structure but one that can be easily scanned through a very simple
+ * 'skip' calculation. The memory allocation is only large enough to
+ * cover the number of blocks requested at creation time. Nodes that
+ * represent blocks beyond that limit, nodes that would never be read
+ * or written, are not allocated, so that the last of the
+ * BLIST_META_RADIX lower level nodes of a some nodes may not be
+ * allocated.
*
* NOTE: the allocator cannot currently allocate more than
* BLIST_BMAP_RADIX blocks per call. It will panic with 'allocation too
@@ -105,6 +105,7 @@ __FBSDID("$FreeBSD$");
#define BLIST_DEBUG
#endif
+#include <sys/errno.h>
#include <sys/types.h>
#include <sys/malloc.h>
#include <sys/sbuf.h>
@@ -118,7 +119,7 @@ __FBSDID("$FreeBSD$");
#define bitcount64(x) __bitcount64((uint64_t)(x))
#define malloc(a,b,c) calloc(a, 1)
#define free(a,b) free(a)
-static __inline int imax(int a, int b) { return (a > b ? a : b); }
+#define ummin(a,b) ((a) < (b) ? (a) : (b))
#include <sys/blist.h>
@@ -179,6 +180,18 @@ radix_to_skip(daddr_t radix)
}
/*
+ * Provide a mask with count bits set, starting as position n.
+ */
+static inline u_daddr_t
+bitrange(int n, int count)
+{
+
+ return (((u_daddr_t)-1 << n) &
+ ((u_daddr_t)-1 >> (BLIST_BMAP_RADIX - (n + count))));
+}
+
+
+/*
* Use binary search, or a faster method, to find the 1 bit in a u_daddr_t.
* Assumes that the argument has only one bit set.
*/
@@ -220,9 +233,7 @@ blist_t
blist_create(daddr_t blocks, int flags)
{
blist_t bl;
- daddr_t i, last_block;
- u_daddr_t nodes, radix, skip;
- int digit;
+ u_daddr_t nodes, radix;
if (blocks == 0)
panic("invalid block count");
@@ -230,30 +241,13 @@ blist_create(daddr_t blocks, int flags)
/*
* Calculate the radix and node count used for scanning.
*/
- last_block = blocks - 1;
+ nodes = 1;
radix = BLIST_BMAP_RADIX;
- while (radix < blocks) {
- if (((last_block / radix + 1) & BLIST_META_MASK) != 0)
- /*
- * We must widen the blist to avoid partially
- * filled nodes.
- */
- last_block |= radix - 1;
+ while (radix <= blocks) {
+ nodes += 1 + (blocks - 1) / radix;
radix *= BLIST_META_RADIX;
}
- /*
- * Count the meta-nodes in the expanded tree, including the final
- * terminator, from the bottom level up to the root.
- */
- nodes = 1;
- if (radix - blocks >= BLIST_BMAP_RADIX)
- nodes++;
- last_block /= BLIST_BMAP_RADIX;
- while (last_block > 0) {
- nodes += last_block + 1;
- last_block /= BLIST_META_RADIX;
- }
bl = malloc(offsetof(struct blist, bl_root[nodes]), M_SWAP, flags |
M_ZERO);
if (bl == NULL)
@@ -261,33 +255,6 @@ blist_create(daddr_t blocks, int flags)
bl->bl_blocks = blocks;
bl->bl_radix = radix;
- bl->bl_cursor = 0;
-
- /*
- * Initialize the empty tree by filling in root values, then initialize
- * just the terminators in the rest of the tree.
- */
- bl->bl_root[0].bm_bighint = 0;
- if (radix == BLIST_BMAP_RADIX)
- bl->bl_root[0].u.bmu_bitmap = 0;
- else
- bl->bl_root[0].u.bmu_avail = 0;
- last_block = blocks - 1;
- i = 0;
- while (radix > BLIST_BMAP_RADIX) {
- radix /= BLIST_META_RADIX;
- skip = radix_to_skip(radix);
- digit = last_block / radix;
- i += 1 + digit * skip;
- if (digit != BLIST_META_MASK) {
- /*
- * Add a terminator.
- */
- bl->bl_root[i + skip].bm_bighint = (daddr_t)-1;
- bl->bl_root[i + skip].u.bmu_bitmap = 0;
- }
- last_block %= radix;
- }
#if defined(BLIST_DEBUG)
printf(
@@ -321,6 +288,9 @@ blist_alloc(blist_t bl, daddr_t count)
{
daddr_t blk;
+ if (count > BLIST_MAX_ALLOC)
+ panic("allocation too large");
+
/*
* This loop iterates at most twice. An allocation failure in the
* first iteration leads to a second iteration only if the cursor was
@@ -331,12 +301,13 @@ blist_alloc(blist_t bl, daddr_t count)
blk = blst_meta_alloc(bl->bl_root, bl->bl_cursor, count,
bl->bl_radix);
if (blk != SWAPBLK_NONE) {
+ bl->bl_avail -= count;
bl->bl_cursor = blk + count;
if (bl->bl_cursor == bl->bl_blocks)
bl->bl_cursor = 0;
return (blk);
- } else if (bl->bl_cursor != 0)
- bl->bl_cursor = 0;
+ }
+ bl->bl_cursor = 0;
}
return (SWAPBLK_NONE);
}
@@ -348,10 +319,7 @@ daddr_t
blist_avail(blist_t bl)
{
- if (bl->bl_radix == BLIST_BMAP_RADIX)
- return (bitcount64(bl->bl_root->u.bmu_bitmap));
- else
- return (bl->bl_root->u.bmu_avail);
+ return (bl->bl_avail);
}
/*
@@ -363,7 +331,10 @@ void
blist_free(blist_t bl, daddr_t blkno, daddr_t count)
{
+ if (blkno < 0 || blkno + count > bl->bl_blocks)
+ panic("freeing invalid range");
blst_meta_free(bl->bl_root, blkno, count, bl->bl_radix);
+ bl->bl_avail += count;
}
/*
@@ -375,8 +346,13 @@ blist_free(blist_t bl, daddr_t blkno, daddr_t count)
daddr_t
blist_fill(blist_t bl, daddr_t blkno, daddr_t count)
{
+ daddr_t filled;
- return (blst_meta_fill(bl->bl_root, blkno, count, bl->bl_radix));
+ if (blkno < 0 || blkno + count > bl->bl_blocks)
+ panic("filling invalid range");
+ filled = blst_meta_fill(bl->bl_root, blkno, count, bl->bl_radix);
+ bl->bl_avail -= filled;
+ return (filled);
}
/*
@@ -414,8 +390,11 @@ blist_resize(blist_t *pbl, daddr_t count, int freenew, int flags)
void
blist_print(blist_t bl)
{
- printf("BLIST cursor = %08jx {\n", (uintmax_t)bl->bl_cursor);
- blst_radix_print(bl->bl_root, 0, bl->bl_radix, 4);
+ printf("BLIST avail = %jd, cursor = %08jx {\n",
+ (uintmax_t)bl->bl_avail, (uintmax_t)bl->bl_cursor);
+
+ if (bl->bl_root->bm_bitmap != 0)
+ blst_radix_print(bl->bl_root, 0, bl->bl_radix, 4);
printf("}\n");
}
@@ -569,16 +548,11 @@ blist_stats(blist_t bl, struct sbuf *s)
* Check for skippable subtrees starting at i.
*/
while (radix > BLIST_BMAP_RADIX) {
- if (bl->bl_root[nodes].u.bmu_avail == 0) {
+ if (bl->bl_root[nodes].bm_bitmap == 0) {
if (gap_stats_counting(stats))
update_gap_stats(stats, i);
break;
}
- if (bl->bl_root[nodes].u.bmu_avail == radix) {
- if (!gap_stats_counting(stats))
- update_gap_stats(stats, i);
- break;
- }
/*
* Skip subtree root.
@@ -590,7 +564,7 @@ blist_stats(blist_t bl, struct sbuf *s)
/*
* Scan leaf.
*/
- mask = bl->bl_root[nodes].u.bmu_bitmap;
+ mask = bl->bl_root[nodes].bm_bitmap;
diff = mask ^ (mask << 1);
if (gap_stats_counting(stats))
diff ^= 1;
@@ -618,7 +592,57 @@ blist_stats(blist_t bl, struct sbuf *s)
*/
/*
- * blist_leaf_alloc() - allocate at a leaf in the radix tree (a bitmap).
+ * BLST_NEXT_LEAF_ALLOC() - allocate the first few blocks in the next leaf.
+ *
+ * 'scan' is a leaf node, associated with a block containing 'blk'.
+ * The next leaf node could be adjacent, or several nodes away if the
+ * least common ancestor of 'scan' and its neighbor is several levels
+ * up. Use 'blk' to determine how many meta-nodes lie between the
+ * leaves. If the next leaf has enough initial bits set, clear them
+ * and clear the bits in the meta nodes on the path up to the least
+ * common ancestor to mark any subtrees made completely empty.
+ */
+static int
+blst_next_leaf_alloc(blmeta_t *scan, daddr_t blk, int count)
+{
+ blmeta_t *next;
+ daddr_t skip;
+ u_daddr_t radix;
+ int digit;
+
+ next = scan + 1;
+ blk += BLIST_BMAP_RADIX;
+ radix = BLIST_BMAP_RADIX;
+ while ((digit = ((blk / radix) & BLIST_META_MASK)) == 0 &&
+ (next->bm_bitmap & 1) == 1) {
+ next++;
+ radix *= BLIST_META_RADIX;
+ }
+ if (((next->bm_bitmap + 1) & ~((u_daddr_t)-1 << count)) != 0) {
+ /*
+ * The next leaf doesn't have enough free blocks at the
+ * beginning to complete the spanning allocation.
+ */
+ return (ENOMEM);
+ }
+ /* Clear the first 'count' bits in the next leaf to allocate. */
+ next->bm_bitmap &= (u_daddr_t)-1 << count;
+
+ /*
+ * Update bitmaps of next-ancestors, up to least common ancestor.
+ */
+ skip = radix_to_skip(radix);
+ while (radix != BLIST_BMAP_RADIX && next->bm_bitmap == 0) {
+ (--next)->bm_bitmap ^= 1;
+ radix /= BLIST_META_RADIX;
+ }
+ if (next->bm_bitmap == 0)
+ scan[-digit * skip].bm_bitmap ^= (u_daddr_t)1 << digit;
+ return (0);
+}
+
+/*
+ * BLST_LEAF_ALLOC() - allocate at a leaf in the radix tree (a bitmap).
*
* This is the core of the allocator and is optimized for the
* BLIST_BMAP_RADIX block allocation case. Otherwise, execution
@@ -633,15 +657,15 @@ blst_leaf_alloc(blmeta_t *scan, daddr_t blk, int count)
range1 = 0;
count1 = count - 1;
num_shifts = fls(count1);
- mask = scan->u.bmu_bitmap;
+ mask = scan->bm_bitmap;
while ((-mask & ~mask) != 0 && num_shifts > 0) {
/*
* If bit i is set in mask, then bits in [i, i+range1] are set
- * in scan->u.bmu_bitmap. The value of range1 is equal to
+ * in scan->bm_bitmap. The value of range1 is equal to
* count1 >> num_shifts. Grow range and reduce num_shifts to 0,
* while preserving these invariants. The updates to mask leave
* fewer bits set, but each bit that remains set represents a
- * longer string of consecutive bits set in scan->u.bmu_bitmap.
+ * longer string of consecutive bits set in scan->bm_bitmap.
* If more updates to mask cannot clear more bits, because mask
* is partitioned with all 0 bits preceding all 1 bits, the loop
* terminates immediately.
@@ -685,31 +709,14 @@ blst_leaf_alloc(blmeta_t *scan, daddr_t blk, int count)
* An allocation within this leaf is impossible, so a successful
* allocation depends on the next leaf providing some of the blocks.
*/
- if (((blk / BLIST_BMAP_RADIX + 1) & BLIST_META_MASK) == 0) {
- /*
- * The next leaf has a different meta-node parent, so it
- * is not necessarily initialized. Update bighint,
- * comparing the range found at the end of mask to the
- * largest earlier range that could have been made to
- * vanish in the initial processing of mask.
- */
- scan->bm_bighint = imax(BLIST_BMAP_RADIX - lo, range1);
- return (SWAPBLK_NONE);
- }
- hi -= BLIST_BMAP_RADIX;
- if (((scan[1].u.bmu_bitmap + 1) & ~((u_daddr_t)-1 << hi)) != 0) {
+ if (blst_next_leaf_alloc(scan, blk, hi - BLIST_BMAP_RADIX) != 0)
/*
- * The next leaf doesn't have enough free blocks at the
- * beginning to complete the spanning allocation. The
- * hint cannot be updated, because the same allocation
- * request could be satisfied later, by this leaf, if
- * the state of the next leaf changes, and without any
- * changes to this leaf.
+ * The hint cannot be updated, because the same
+ * allocation request could be satisfied later, by this
+ * leaf, if the state of the next leaf changes, and
+ * without any changes to this leaf.
*/
return (SWAPBLK_NONE);
- }
- /* Clear the first 'hi' bits in the next leaf, allocating them. */
- scan[1].u.bmu_bitmap &= (u_daddr_t)-1 << hi;
hi = BLIST_BMAP_RADIX;
}
@@ -724,12 +731,9 @@ blst_leaf_alloc(blmeta_t *scan, daddr_t blk, int count)
} else {
/* Clear the bits of mask at position 'hi' and higher. */
mask &= (u_daddr_t)-1 >> (BLIST_BMAP_RADIX - hi);
- /* If this allocation uses all the bits, clear the hint. */
- if (mask == scan->u.bmu_bitmap)
- scan->bm_bighint = 0;
}
/* Clear the allocated bits from this leaf. */
- scan->u.bmu_bitmap &= ~mask;
+ scan->bm_bitmap &= ~mask;
return ((blk & ~BLIST_BMAP_MASK) + lo);
}
@@ -744,81 +748,61 @@ blst_leaf_alloc(blmeta_t *scan, daddr_t blk, int count)
static daddr_t
blst_meta_alloc(blmeta_t *scan, daddr_t cursor, daddr_t count, u_daddr_t radix)
{
- daddr_t blk, i, next_skip, r, skip;
- int child;
+ daddr_t blk, i, r, skip;
+ u_daddr_t bit, mask;
bool scan_from_start;
+ int digit;
if (radix == BLIST_BMAP_RADIX)
return (blst_leaf_alloc(scan, cursor, count));
- if (scan->u.bmu_avail < count) {
- /*
- * The meta node's hint must be too large if the allocation
- * exceeds the number of free blocks. Reduce the hint, and
- * return failure.
- */
- scan->bm_bighint = scan->u.bmu_avail;
- return (SWAPBLK_NONE);
- }
blk = cursor & -radix;
+ scan_from_start = (cursor == blk);
+ radix /= BLIST_META_RADIX;
skip = radix_to_skip(radix);
- next_skip = skip / BLIST_META_RADIX;
+ mask = scan->bm_bitmap;
+
+ /* Discard any candidates that appear before cursor. */
+ digit = (cursor / radix) & BLIST_META_MASK;
+ mask &= (u_daddr_t)-1 << digit;
/*
- * An ALL-FREE meta node requires special handling before allocating
- * any of its blocks.
+ * If the first try is for a block that includes the cursor, pre-undo
+ * the digit * radix offset in the first call; otherwise, ignore the
+ * cursor entirely.
*/
- if (scan->u.bmu_avail == radix) {
- radix /= BLIST_META_RADIX;
-
- /*
- * Reinitialize each of the meta node's children. An ALL-FREE
- * meta node cannot have a terminator in any subtree.
- */
- for (i = 1; i < skip; i += next_skip) {
- if (next_skip == 1)
- scan[i].u.bmu_bitmap = (u_daddr_t)-1;
- else
- scan[i].u.bmu_avail = radix;
- scan[i].bm_bighint = radix;
- }
- } else {
- radix /= BLIST_META_RADIX;
- }
+ if (((mask >> digit) & 1) == 1)
+ cursor -= digit * radix;
+ else
+ cursor = blk;
- if (count > radix) {
- /*
- * The allocation exceeds the number of blocks that are
- * managed by a subtree of this meta node.
- */
- panic("allocation too large");
- }
- scan_from_start = cursor == blk;
- child = (cursor - blk) / radix;
- blk += child * radix;
- for (i = 1 + child * next_skip; i < skip; i += next_skip) {
+ /*
+ * Examine the nonempty subtree associated with each bit set in mask.
+ */
+ do {
+ bit = mask & -mask;
+ digit = bitpos(bit);
+ i = 1 + digit * skip;
if (count <= scan[i].bm_bighint) {
/*
* The allocation might fit beginning in the i'th subtree.
*/
- r = blst_meta_alloc(&scan[i],
- cursor > blk ? cursor : blk, count, radix);
+ r = blst_meta_alloc(&scan[i], cursor + digit * radix,
+ count, radix);
if (r != SWAPBLK_NONE) {
- scan->u.bmu_avail -= count;
+ if (scan[i].bm_bitmap == 0)
+ scan->bm_bitmap ^= bit;
return (r);
}
- } else if (scan[i].bm_bighint == (daddr_t)-1) {
- /*
- * Terminator
- */
- break;
}
- blk += radix;
- }
+ cursor = blk;
+ } while ((mask ^= bit) != 0);
/*
- * We couldn't allocate count in this subtree, update bighint.
+ * We couldn't allocate count in this subtree. If the whole tree was
+ * scanned, and the last tree node is allocated, update bighint.
*/
- if (scan_from_start && scan->bm_bighint >= count)
+ if (scan_from_start && !(digit == BLIST_META_RADIX - 1 &&
+ scan[i].bm_bighint == BLIST_MAX_ALLOC))
scan->bm_bighint = count - 1;
return (SWAPBLK_NONE);
@@ -832,7 +816,6 @@ static void
blst_leaf_free(blmeta_t *scan, daddr_t blk, int count)
{
u_daddr_t mask;
- int n;
/*
* free some data in this bitmap
@@ -840,20 +823,10 @@ blst_leaf_free(blmeta_t *scan, daddr_t blk, int count)
* \_________/\__/
* count n
*/
- n = blk & BLIST_BMAP_MASK;
- mask = ((u_daddr_t)-1 << n) &
- ((u_daddr_t)-1 >> (BLIST_BMAP_RADIX - count - n));
- if (scan->u.bmu_bitmap & mask)
+ mask = bitrange(blk & BLIST_BMAP_MASK, count);
+ if (scan->bm_bitmap & mask)
panic("freeing free block");
- scan->u.bmu_bitmap |= mask;
-
- /*
- * We could probably do a better job here. We are required to make
- * bighint at least as large as the biggest contiguous block of
- * data. If we just shoehorn it, a little extra overhead will
- * be incured on the next allocation (but only that one typically).
- */
- scan->bm_bighint = BLIST_BMAP_RADIX;
+ scan->bm_bitmap |= mask;
}
/*
@@ -869,79 +842,37 @@ blst_leaf_free(blmeta_t *scan, daddr_t blk, int count)
static void
blst_meta_free(blmeta_t *scan, daddr_t freeBlk, daddr_t count, u_daddr_t radix)
{
- daddr_t blk, i, next_skip, skip, v;
- int child;
-
- if (scan->bm_bighint == (daddr_t)-1)
- panic("freeing invalid range");
- if (radix == BLIST_BMAP_RADIX)
- return (blst_leaf_free(scan, freeBlk, count));
- skip = radix_to_skip(radix);
- next_skip = skip / BLIST_META_RADIX;
-
- if (scan->u.bmu_avail == 0) {
- /*
- * ALL-ALLOCATED special case, with possible
- * shortcut to ALL-FREE special case.
- */
- scan->u.bmu_avail = count;
- scan->bm_bighint = count;
-
- if (count != radix) {
- for (i = 1; i < skip; i += next_skip) {
- if (scan[i].bm_bighint == (daddr_t)-1)
- break;
- scan[i].bm_bighint = 0;
- if (next_skip == 1) {
- scan[i].u.bmu_bitmap = 0;
- } else {
- scan[i].u.bmu_avail = 0;
- }
- }
- /* fall through */
- }
- } else {
- scan->u.bmu_avail += count;
- /* scan->bm_bighint = radix; */
- }
+ daddr_t blk, endBlk, i, skip;
+ int digit, endDigit;
/*
- * ALL-FREE special case.
+ * We could probably do a better job here. We are required to make
+ * bighint at least as large as the biggest allocable block of data.
+ * If we just shoehorn it, a little extra overhead will be incurred
+ * on the next allocation (but only that one typically).
*/
+ scan->bm_bighint = BLIST_MAX_ALLOC;
- if (scan->u.bmu_avail == radix)
- return;
- if (scan->u.bmu_avail > radix)
- panic("blst_meta_free: freeing already free blocks (%lld) %lld/%lld",
- (long long)count, (long long)scan->u.bmu_avail,
- (long long)radix);
-
- /*
- * Break the free down into its components
- */
+ if (radix == BLIST_BMAP_RADIX)
+ return (blst_leaf_free(scan, freeBlk, count));
- blk = freeBlk & -radix;
+ endBlk = ummin(freeBlk + count, (freeBlk + radix) & -radix);
radix /= BLIST_META_RADIX;
-
- child = (freeBlk - blk) / radix;
- blk += child * radix;
- i = 1 + child * next_skip;
- while (i < skip && blk < freeBlk + count) {
- v = blk + radix - freeBlk;
- if (v > count)
- v = count;
- blst_meta_free(&scan[i], freeBlk, v, radix);
- if (scan->bm_bighint < scan[i].bm_bighint)
- scan->bm_bighint = scan[i].bm_bighint;
- count -= v;
- freeBlk += v;
+ skip = radix_to_skip(radix);
+ blk = freeBlk & -radix;
+ digit = (blk / radix) & BLIST_META_MASK;
+ endDigit = 1 + (((endBlk - 1) / radix) & BLIST_META_MASK);
+ scan->bm_bitmap |= bitrange(digit, endDigit - digit);
+ for (i = 1 + digit * skip; blk < endBlk; i += skip) {
blk += radix;
- i += next_skip;
+ count = ummin(blk, endBlk) - freeBlk;
+ blst_meta_free(&scan[i], freeBlk, count, radix);
+ freeBlk = blk;
}
}
/*
- * BLIST_RADIX_COPY() - copy one radix tree to another
+ * BLST_COPY() - copy one radix tree to another
*
* Locates free space in the source tree and frees it in the destination
* tree. The space may not already be free in the destination.
@@ -950,21 +881,21 @@ static void
blst_copy(blmeta_t *scan, daddr_t blk, daddr_t radix, blist_t dest,
daddr_t count)
{
- daddr_t i, next_skip, skip;
+ daddr_t endBlk, i, skip;
/*
* Leaf node
*/
if (radix == BLIST_BMAP_RADIX) {
- u_daddr_t v = scan->u.bmu_bitmap;
+ u_daddr_t v = scan->bm_bitmap;
if (v == (u_daddr_t)-1) {
blist_free(dest, blk, count);
} else if (v != 0) {
int i;
- for (i = 0; i < BLIST_BMAP_RADIX && i < count; ++i) {
+ for (i = 0; i < count; ++i) {
if (v & ((u_daddr_t)1 << i))
blist_free(dest, blk + i, 1);
}
@@ -976,42 +907,22 @@ blst_copy(blmeta_t *scan, daddr_t blk, daddr_t radix, blist_t dest,
* Meta node
*/
- if (scan->u.bmu_avail == 0) {
+ if (scan->bm_bitmap == 0) {
/*
* Source all allocated, leave dest allocated
*/
return;
}
- if (scan->u.bmu_avail == radix) {
- /*
- * Source all free, free entire dest
- */
- if (count < radix)
- blist_free(dest, blk, count);
- else
- blist_free(dest, blk, radix);
- return;
- }
-
- skip = radix_to_skip(radix);
- next_skip = skip / BLIST_META_RADIX;
+ endBlk = blk + count;
radix /= BLIST_META_RADIX;
-
- for (i = 1; count && i < skip; i += next_skip) {
- if (scan[i].bm_bighint == (daddr_t)-1)
- break;
-
- if (count >= radix) {
- blst_copy(&scan[i], blk, radix, dest, radix);
- count -= radix;
- } else {
- if (count) {
- blst_copy(&scan[i], blk, radix, dest, count);
- }
- count = 0;
- }
+ skip = radix_to_skip(radix);
+ for (i = 1; blk < endBlk; i += skip) {
blk += radix;
+ count = radix;
+ if (blk >= endBlk)
+ count -= blk - endBlk;
+ blst_copy(&scan[i], blk - radix, radix, dest, count);
}
}
@@ -1027,16 +938,13 @@ blst_leaf_fill(blmeta_t *scan, daddr_t blk, int count)
{
daddr_t nblks;
u_daddr_t mask;
- int n;
- n = blk & BLIST_BMAP_MASK;
- mask = ((u_daddr_t)-1 << n) &
- ((u_daddr_t)-1 >> (BLIST_BMAP_RADIX - count - n));
+ mask = bitrange(blk & BLIST_BMAP_MASK, count);
/* Count the number of blocks that we are allocating. */
- nblks = bitcount64(scan->u.bmu_bitmap & mask);
+ nblks = bitcount64(scan->bm_bitmap & mask);
- scan->u.bmu_bitmap &= ~mask;
+ scan->bm_bitmap &= ~mask;
return (nblks);
}
@@ -1051,70 +959,27 @@ blst_leaf_fill(blmeta_t *scan, daddr_t blk, int count)
static daddr_t
blst_meta_fill(blmeta_t *scan, daddr_t allocBlk, daddr_t count, u_daddr_t radix)
{
- daddr_t blk, i, nblks, next_skip, skip, v;
- int child;
+ daddr_t blk, endBlk, i, nblks, skip;
+ int digit;
- if (scan->bm_bighint == (daddr_t)-1)
- panic("filling invalid range");
- if (count > radix) {
- /*
- * The allocation exceeds the number of blocks that are
- * managed by this node.
- */
- panic("fill too large");
- }
if (radix == BLIST_BMAP_RADIX)
return (blst_leaf_fill(scan, allocBlk, count));
- if (count == radix || scan->u.bmu_avail == 0) {
- /*
- * ALL-ALLOCATED special case
- */
- nblks = scan->u.bmu_avail;
- scan->u.bmu_avail = 0;
- scan->bm_bighint = 0;
- return (nblks);
- }
+
+ endBlk = ummin(allocBlk + count, (allocBlk + radix) & -radix);
+ radix /= BLIST_META_RADIX;
skip = radix_to_skip(radix);
- next_skip = skip / BLIST_META_RADIX;
blk = allocBlk & -radix;
-
- /*
- * An ALL-FREE meta node requires special handling before allocating
- * any of its blocks.
- */
- if (scan->u.bmu_avail == radix) {
- radix /= BLIST_META_RADIX;
-
- /*
- * Reinitialize each of the meta node's children. An ALL-FREE
- * meta node cannot have a terminator in any subtree.
- */
- for (i = 1; i < skip; i += next_skip) {
- if (next_skip == 1)
- scan[i].u.bmu_bitmap = (u_daddr_t)-1;
- else
- scan[i].u.bmu_avail = radix;
- scan[i].bm_bighint = radix;
- }
- } else {
- radix /= BLIST_META_RADIX;
- }
-
nblks = 0;
- child = (allocBlk - blk) / radix;
- blk += child * radix;
- i = 1 + child * next_skip;
- while (i < skip && blk < allocBlk + count) {
- v = blk + radix - allocBlk;
- if (v > count)
- v = count;
- nblks += blst_meta_fill(&scan[i], allocBlk, v, radix);
- count -= v;
- allocBlk += v;
+ while (blk < endBlk) {
+ digit = (blk / radix) & BLIST_META_MASK;
+ i = 1 + digit * skip;
blk += radix;
- i += next_skip;
+ count = ummin(blk, endBlk) - allocBlk;
+ nblks += blst_meta_fill(&scan[i], allocBlk, count, radix);
+ if (scan[i].bm_bitmap == 0)
+ scan->bm_bitmap &= ~((u_daddr_t)1 << digit);
+ allocBlk = blk;
}
- scan->u.bmu_avail -= nblks;
return (nblks);
}
@@ -1123,64 +988,44 @@ blst_meta_fill(blmeta_t *scan, daddr_t allocBlk, daddr_t count, u_daddr_t radix)
static void
blst_radix_print(blmeta_t *scan, daddr_t blk, daddr_t radix, int tab)
{
- daddr_t i, next_skip, skip;
+ daddr_t skip;
+ u_daddr_t bit, mask;
+ int digit;
if (radix == BLIST_BMAP_RADIX) {
printf(
- "%*.*s(%08llx,%lld): bitmap %016llx big=%lld\n",
+ "%*.*s(%08llx,%lld): bitmap %0*llx big=%lld\n",
tab, tab, "",
(long long)blk, (long long)radix,
- (long long)scan->u.bmu_bitmap,
+ 1 + (BLIST_BMAP_RADIX - 1) / 4,
+ (long long)scan->bm_bitmap,
(long long)scan->bm_bighint
);
return;
}
- if (scan->u.bmu_avail == 0) {
- printf(
- "%*.*s(%08llx,%lld) ALL ALLOCATED\n",
- tab, tab, "",
- (long long)blk,
- (long long)radix
- );
- return;
- }
- if (scan->u.bmu_avail == radix) {
- printf(
- "%*.*s(%08llx,%lld) ALL FREE\n",
- tab, tab, "",
- (long long)blk,
- (long long)radix
- );
- return;
- }
-
printf(
- "%*.*s(%08llx,%lld): subtree (%lld/%lld) big=%lld {\n",
+ "%*.*s(%08llx): subtree (%lld/%lld) bitmap %0*llx big=%lld {\n",
tab, tab, "",
(long long)blk, (long long)radix,
- (long long)scan->u.bmu_avail,
(long long)radix,
+ 1 + (BLIST_META_RADIX - 1) / 4,
+ (long long)scan->bm_bitmap,
(long long)scan->bm_bighint
);
- skip = radix_to_skip(radix);
- next_skip = skip / BLIST_META_RADIX;
radix /= BLIST_META_RADIX;
+ skip = radix_to_skip(radix);
tab += 4;
- for (i = 1; i < skip; i += next_skip) {
- if (scan[i].bm_bighint == (daddr_t)-1) {
- printf(
- "%*.*s(%08llx,%lld): Terminator\n",
- tab, tab, "",
- (long long)blk, (long long)radix
- );
- break;
- }
- blst_radix_print(&scan[i], blk, radix, tab);
- blk += radix;
- }
+ mask = scan->bm_bitmap;
+ /* Examine the nonempty subtree associated with each bit set in mask */
+ do {
+ bit = mask & -mask;
+ digit = bitpos(bit);
+ blst_radix_print(&scan[1 + digit * skip], blk + digit * radix,
+ radix, tab);
+ } while ((mask ^= bit) != 0);
tab -= 4;
printf(
@@ -1196,7 +1041,7 @@ blst_radix_print(blmeta_t *scan, daddr_t blk, daddr_t radix, int tab)
int
main(int ac, char **av)
{
- int size = 1024;
+ int size = BLIST_META_RADIX * BLIST_BMAP_RADIX;
int i;
blist_t bl;
struct sbuf *s;
diff --git a/sys/kern/subr_epoch.c b/sys/kern/subr_epoch.c
index a63f669fea75..9104f1e0880a 100644
--- a/sys/kern/subr_epoch.c
+++ b/sys/kern/subr_epoch.c
@@ -55,6 +55,27 @@ __FBSDID("$FreeBSD$");
static MALLOC_DEFINE(M_EPOCH, "epoch", "epoch based reclamation");
+#ifdef __amd64__
+#define EPOCH_ALIGN CACHE_LINE_SIZE*2
+#else
+#define EPOCH_ALIGN CACHE_LINE_SIZE
+#endif
+
+TAILQ_HEAD (epoch_tdlist, epoch_tracker);
+typedef struct epoch_record {
+ ck_epoch_record_t er_record;
+ volatile struct epoch_tdlist er_tdlist;
+ volatile uint32_t er_gen;
+ uint32_t er_cpuid;
+} __aligned(EPOCH_ALIGN) *epoch_record_t;
+
+struct epoch {
+ struct ck_epoch e_epoch __aligned(EPOCH_ALIGN);
+ epoch_record_t e_pcpu_record;
+ int e_idx;
+ int e_flags;
+};
+
/* arbitrary --- needs benchmarking */
#define MAX_ADAPTIVE_SPIN 100
#define MAX_EPOCHS 64
@@ -119,11 +140,15 @@ epoch_init(void *arg __unused)
epoch_call_count = counter_u64_alloc(M_WAITOK);
epoch_call_task_count = counter_u64_alloc(M_WAITOK);
- pcpu_zone_record = uma_zcreate("epoch_record pcpu", sizeof(struct epoch_record),
- NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_PCPU);
+ pcpu_zone_record = uma_zcreate("epoch_record pcpu",
+ sizeof(struct epoch_record), NULL, NULL, NULL, NULL,
+ UMA_ALIGN_PTR, UMA_ZONE_PCPU);
CPU_FOREACH(cpu) {
- GROUPTASK_INIT(DPCPU_ID_PTR(cpu, epoch_cb_task), 0, epoch_call_task, NULL);
- taskqgroup_attach_cpu(qgroup_softirq, DPCPU_ID_PTR(cpu, epoch_cb_task), NULL, cpu, -1, "epoch call task");
+ GROUPTASK_INIT(DPCPU_ID_PTR(cpu, epoch_cb_task), 0,
+ epoch_call_task, NULL);
+ taskqgroup_attach_cpu(qgroup_softirq,
+ DPCPU_ID_PTR(cpu, epoch_cb_task), NULL, cpu, -1,
+ "epoch call task");
}
inited = 1;
global_epoch = epoch_alloc(0);
@@ -150,13 +175,21 @@ epoch_ctor(epoch_t epoch)
CPU_FOREACH(cpu) {
er = zpcpu_get_cpu(epoch->e_pcpu_record, cpu);
bzero(er, sizeof(*er));
- ck_epoch_register(&epoch->e_epoch, &er->er_read_record, NULL);
- ck_epoch_register(&epoch->e_epoch, &er->er_write_record, NULL);
+ ck_epoch_register(&epoch->e_epoch, &er->er_record, NULL);
TAILQ_INIT((struct threadlist *)(uintptr_t)&er->er_tdlist);
er->er_cpuid = cpu;
}
}
+static void
+epoch_adjust_prio(struct thread *td, u_char prio)
+{
+
+ thread_lock(td);
+ sched_prio(td, prio);
+ thread_unlock(td);
+}
+
epoch_t
epoch_alloc(int flags)
{
@@ -192,51 +225,126 @@ epoch_free(epoch_t epoch)
free(epoch, M_EPOCH);
}
+static epoch_record_t
+epoch_currecord(epoch_t epoch)
+{
+
+ return (zpcpu_get_cpu(epoch->e_pcpu_record, curcpu));
+}
+
+#define INIT_CHECK(epoch) \
+ do { \
+ if (__predict_false((epoch) == NULL)) \
+ return; \
+ } while (0)
+
void
-epoch_enter_preempt_KBI(epoch_t epoch, epoch_tracker_t et)
+epoch_enter_preempt(epoch_t epoch, epoch_tracker_t et)
{
+ struct epoch_record *er;
+ struct thread *td;
+
+ MPASS(cold || epoch != NULL);
+ INIT_CHECK(epoch);
+ MPASS(epoch->e_flags & EPOCH_PREEMPT);
+#ifdef EPOCH_TRACKER_DEBUG
+ et->et_magic_pre = EPOCH_MAGIC0;
+ et->et_magic_post = EPOCH_MAGIC1;
+#endif
+ td = curthread;
+ et->et_td = td;
+ td->td_epochnest++;
+ critical_enter();
+ sched_pin();
- epoch_enter_preempt(epoch, et);
+ td->td_pre_epoch_prio = td->td_priority;
+ er = epoch_currecord(epoch);
+ TAILQ_INSERT_TAIL(&er->er_tdlist, et, et_link);
+ ck_epoch_begin(&er->er_record, &et->et_section);
+ critical_exit();
}
void
-epoch_exit_preempt_KBI(epoch_t epoch, epoch_tracker_t et)
+epoch_enter(epoch_t epoch)
{
+ struct thread *td;
+ epoch_record_t er;
- epoch_exit_preempt(epoch, et);
+ MPASS(cold || epoch != NULL);
+ INIT_CHECK(epoch);
+ td = curthread;
+
+ td->td_epochnest++;
+ critical_enter();
+ er = epoch_currecord(epoch);
+ ck_epoch_begin(&er->er_record, NULL);
}
void
-epoch_enter_KBI(epoch_t epoch)
+epoch_exit_preempt(epoch_t epoch, epoch_tracker_t et)
{
+ struct epoch_record *er;
+ struct thread *td;
- epoch_enter(epoch);
+ INIT_CHECK(epoch);
+ td = curthread;
+ critical_enter();
+ sched_unpin();
+ MPASS(td->td_epochnest);
+ td->td_epochnest--;
+ er = epoch_currecord(epoch);
+ MPASS(epoch->e_flags & EPOCH_PREEMPT);
+ MPASS(et != NULL);
+ MPASS(et->et_td == td);
+#ifdef EPOCH_TRACKER_DEBUG
+ MPASS(et->et_magic_pre == EPOCH_MAGIC0);
+ MPASS(et->et_magic_post == EPOCH_MAGIC1);
+ et->et_magic_pre = 0;
+ et->et_magic_post = 0;
+#endif
+#ifdef INVARIANTS
+ et->et_td = (void*)0xDEADBEEF;
+#endif
+ ck_epoch_end(&er->er_record, &et->et_section);
+ TAILQ_REMOVE(&er->er_tdlist, et, et_link);
+ er->er_gen++;
+ if (__predict_false(td->td_pre_epoch_prio != td->td_priority))
+ epoch_adjust_prio(td, td->td_pre_epoch_prio);
+ critical_exit();
}
void
-epoch_exit_KBI(epoch_t epoch)
+epoch_exit(epoch_t epoch)
{
+ struct thread *td;
+ epoch_record_t er;
- epoch_exit(epoch);
+ INIT_CHECK(epoch);
+ td = curthread;
+ MPASS(td->td_epochnest);
+ td->td_epochnest--;
+ er = epoch_currecord(epoch);
+ ck_epoch_end(&er->er_record, NULL);
+ critical_exit();
}
/*
- * epoch_block_handler_preempt is a callback from the ck code when another thread is
- * currently in an epoch section.
+ * epoch_block_handler_preempt() is a callback from the CK code when another
+ * thread is currently in an epoch section.
*/
static void
-epoch_block_handler_preempt(struct ck_epoch *global __unused, ck_epoch_record_t *cr,
- void *arg __unused)
+epoch_block_handler_preempt(struct ck_epoch *global __unused,
+ ck_epoch_record_t *cr, void *arg __unused)
{
epoch_record_t record;
struct thread *td, *owner, *curwaittd;
- struct epoch_thread *tdwait;
+ struct epoch_tracker *tdwait;
struct turnstile *ts;
struct lock_object *lock;
int spincount, gen;
int locksheld __unused;
- record = __containerof(cr, struct epoch_record, er_read_record);
+ record = __containerof(cr, struct epoch_record, er_record);
td = curthread;
locksheld = td->td_locks;
spincount = 0;
@@ -318,25 +426,27 @@ epoch_block_handler_preempt(struct ck_epoch *global __unused, ck_epoch_record_t
if (TD_IS_INHIBITED(curwaittd) && TD_ON_LOCK(curwaittd) &&
((ts = curwaittd->td_blocked) != NULL)) {
/*
- * We unlock td to allow turnstile_wait to reacquire the
- * the thread lock. Before unlocking it we enter a critical
- * section to prevent preemption after we reenable interrupts
- * by dropping the thread lock in order to prevent curwaittd
- * from getting to run.
+ * We unlock td to allow turnstile_wait to reacquire
+ * the thread lock. Before unlocking it we enter a
+ * critical section to prevent preemption after we
+ * reenable interrupts by dropping the thread lock in
+ * order to prevent curwaittd from getting to run.
*/
critical_enter();
thread_unlock(td);
owner = turnstile_lock(ts, &lock);
/*
- * The owner pointer indicates that the lock succeeded. Only
- * in case we hold the lock and the turnstile we locked is still
- * the one that curwaittd is blocked on can we continue. Otherwise
- * The turnstile pointer has been changed out from underneath
- * us, as in the case where the lock holder has signalled curwaittd,
+ * The owner pointer indicates that the lock succeeded.
+ * Only in case we hold the lock and the turnstile we
+ * locked is still the one that curwaittd is blocked on
+ * can we continue. Otherwise the turnstile pointer has
+ * been changed out from underneath us, as in the case
+ * where the lock holder has signalled curwaittd,
* and we need to continue.
*/
if (owner != NULL && ts == curwaittd->td_blocked) {
- MPASS(TD_IS_INHIBITED(curwaittd) && TD_ON_LOCK(curwaittd));
+ MPASS(TD_IS_INHIBITED(curwaittd) &&
+ TD_ON_LOCK(curwaittd));
critical_exit();
turnstile_wait(ts, owner, curwaittd->td_tsqueue);
counter_u64_add(turnstile_count, 1);
@@ -386,9 +496,8 @@ epoch_wait_preempt(epoch_t epoch)
if ((epoch->e_flags & EPOCH_LOCKED) == 0)
WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL,
"epoch_wait() can be long running");
- KASSERT(!in_epoch(epoch),
- ("epoch_wait_preempt() called in the middle "
- "of an epoch section of the same epoch"));
+ KASSERT(!in_epoch(epoch), ("epoch_wait_preempt() called in the middle "
+ "of an epoch section of the same epoch"));
#endif
thread_lock(td);
DROP_GIANT();
@@ -401,7 +510,8 @@ epoch_wait_preempt(epoch_t epoch)
td->td_pinned = 0;
sched_bind(td, old_cpu);
- ck_epoch_synchronize_wait(&epoch->e_epoch, epoch_block_handler_preempt, NULL);
+ ck_epoch_synchronize_wait(&epoch->e_epoch, epoch_block_handler_preempt,
+ NULL);
/* restore CPU binding, if any */
if (was_bound != 0) {
@@ -462,7 +572,7 @@ epoch_call(epoch_t epoch, epoch_context_t ctx, void (*callback) (epoch_context_t
critical_enter();
*DPCPU_PTR(epoch_cb_count) += 1;
er = epoch_currecord(epoch);
- ck_epoch_call(&er->er_write_record, cb, (ck_epoch_cb_t *)callback);
+ ck_epoch_call(&er->er_record, cb, (ck_epoch_cb_t *)callback);
critical_exit();
return;
boottime:
@@ -486,7 +596,7 @@ epoch_call_task(void *arg __unused)
if (__predict_false((epoch = allepochs[i]) == NULL))
continue;
er = epoch_currecord(epoch);
- record = &er->er_write_record;
+ record = &er->er_record;
if ((npending = record->n_pending) == 0)
continue;
ck_epoch_poll_deferred(record, &cb_stack);
@@ -502,7 +612,7 @@ epoch_call_task(void *arg __unused)
head = ck_stack_batch_pop_npsc(&cb_stack);
for (cursor = head; cursor != NULL; cursor = next) {
struct ck_epoch_entry *entry =
- ck_epoch_entry_container(cursor);
+ ck_epoch_entry_container(cursor);
next = CK_STACK_NEXT(cursor);
entry->function(entry);
@@ -512,7 +622,7 @@ epoch_call_task(void *arg __unused)
int
in_epoch_verbose(epoch_t epoch, int dump_onfail)
{
- struct epoch_thread *tdwait;
+ struct epoch_tracker *tdwait;
struct thread *td;
epoch_record_t er;
@@ -548,9 +658,15 @@ in_epoch(epoch_t epoch)
}
void
-epoch_adjust_prio(struct thread *td, u_char prio)
+epoch_thread_init(struct thread *td)
{
- thread_lock(td);
- sched_prio(td, prio);
- thread_unlock(td);
+
+ td->td_et = malloc(sizeof(struct epoch_tracker), M_EPOCH, M_WAITOK);
+}
+
+void
+epoch_thread_fini(struct thread *td)
+{
+
+ free(td->td_et, M_EPOCH);
}
diff --git a/sys/net/if.c b/sys/net/if.c
index 4a89e37e5f53..15b4d7c12d1e 100644
--- a/sys/net/if.c
+++ b/sys/net/if.c
@@ -1767,35 +1767,29 @@ if_data_copy(struct ifnet *ifp, struct if_data *ifd)
void
if_addr_rlock(struct ifnet *ifp)
{
- MPASS(*(uint64_t *)&ifp->if_addr_et == 0);
- epoch_enter_preempt(net_epoch_preempt, &ifp->if_addr_et);
+
+ epoch_enter_preempt(net_epoch_preempt, curthread->td_et);
}
void
if_addr_runlock(struct ifnet *ifp)
{
- epoch_exit_preempt(net_epoch_preempt, &ifp->if_addr_et);
-#ifdef INVARIANTS
- bzero(&ifp->if_addr_et, sizeof(struct epoch_tracker));
-#endif
+
+ epoch_exit_preempt(net_epoch_preempt, curthread->td_et);
}
void
if_maddr_rlock(if_t ifp)
{
- MPASS(*(uint64_t *)&ifp->if_maddr_et == 0);
- epoch_enter_preempt(net_epoch_preempt, &ifp->if_maddr_et);
+ epoch_enter_preempt(net_epoch_preempt, curthread->td_et);
}
void
if_maddr_runlock(if_t ifp)
{
- epoch_exit_preempt(net_epoch_preempt, &ifp->if_maddr_et);
-#ifdef INVARIANTS
- bzero(&ifp->if_maddr_et, sizeof(struct epoch_tracker));
-#endif
+ epoch_exit_preempt(net_epoch_preempt, curthread->td_et);
}
/*
diff --git a/sys/net/if_var.h b/sys/net/if_var.h
index a7edae305223..37c08e68156a 100644
--- a/sys/net/if_var.h
+++ b/sys/net/if_var.h
@@ -381,8 +381,6 @@ struct ifnet {
*/
struct netdump_methods *if_netdump_methods;
struct epoch_context if_epoch_ctx;
- struct epoch_tracker if_addr_et;
- struct epoch_tracker if_maddr_et;
/*
* Spare fields to be added before branching a stable branch, so
diff --git a/sys/powerpc/conf/GENERIC64 b/sys/powerpc/conf/GENERIC64
index fd24daff91e4..b395bccf7778 100644
--- a/sys/powerpc/conf/GENERIC64
+++ b/sys/powerpc/conf/GENERIC64
@@ -39,6 +39,10 @@ options PREEMPTION #Enable kernel thread preemption
options VIMAGE # Subsystem virtualization, e.g. VNET
options INET #InterNETworking
options INET6 #IPv6 communications protocols
+options IPSEC # IP (v4/v6) security
+options IPSEC_SUPPORT # Allow kldload of ipsec and tcpmd5
+options TCP_OFFLOAD # TCP offload
+options TCP_BLACKBOX # Enhanced TCP event logging
options TCP_HHOOK # hhook(9) framework for TCP
options TCP_RFC7413 # TCP Fast Open
options SCTP #Stream Control Transmission Protocol
@@ -83,6 +87,9 @@ options MAC # TrustedBSD MAC Framework
options KDTRACE_HOOKS # Kernel DTrace hooks
options DDB_CTF # Kernel ELF linker loads CTF data
options INCLUDE_CONFIG_FILE # Include this file in kernel
+options RACCT # Resource accounting framework
+options RACCT_DEFAULT_TO_DISABLED # Set kern.racct.enable=0 by default
+options RCTL # Resource limits
# Debugging support. Always need this:
options KDB # Enable kernel debugger support.
@@ -136,10 +143,12 @@ device sym # NCR/Symbios/LSI Logic 53C8XX/53C1010/53C1510D
# ATA/SCSI peripherals
device scbus # SCSI bus (required for ATA/SCSI)
+device ch # SCSI media changers
device da # Direct Access (disks)
device sa # Sequential Access (tape etc)
device cd # CD
device pass # Passthrough device (direct ATA/SCSI access)
+device ses # Enclosure Service (SES and SAF-TE)
# vt is the default console driver, resembling an SCO console
device vt # Core console driver
@@ -168,6 +177,7 @@ device re # RealTek 8139C+/8169/8169S/8110S
device rl # RealTek 8129/8139
# Pseudo devices.
+device crypto # core crypto support
device loop # Network loopback
device random # Entropy device
device ether # Ethernet support
@@ -193,10 +203,8 @@ device usb # USB Bus (required)
device uhid # "Human Interface Devices"
device ukbd # Keyboard
options KBD_INSTALL_CDEV # install a CDEV entry in /dev
-device ulpt # Printer
device umass # Disks/Mass storage - Requires scbus and da0
device ums # Mouse
-device urio # Diamond Rio 500 MP3 player
# USB Ethernet
device aue # ADMtek USB Ethernet
device axe # ASIX Electronics USB Ethernet
@@ -236,3 +244,5 @@ device sound # Generic sound driver (required)
device snd_ai2s # Apple I2S audio
device snd_uaudio # USB Audio
+# Netmap provides direct access to TX/RX rings on supported NICs
+device netmap # netmap(4) support
diff --git a/sys/riscv/include/cpu.h b/sys/riscv/include/cpu.h
index 989f8946333d..79c6f730f2a6 100644
--- a/sys/riscv/include/cpu.h
+++ b/sys/riscv/include/cpu.h
@@ -38,6 +38,7 @@
#define _MACHINE_CPU_H_
#include <machine/atomic.h>
+#include <machine/cpufunc.h>
#include <machine/frame.h>
#define TRAPF_PC(tfp) ((tfp)->tf_ra)
@@ -86,8 +87,7 @@ static __inline uint64_t
get_cyclecount(void)
{
- /* TODO: This is bogus */
- return (1);
+ return (rdcycle());
}
#endif
diff --git a/sys/riscv/include/cpufunc.h b/sys/riscv/include/cpufunc.h
index e1979d5d2c3f..625c17ebf7dc 100644
--- a/sys/riscv/include/cpufunc.h
+++ b/sys/riscv/include/cpufunc.h
@@ -104,6 +104,11 @@ sfence_vma_page(uintptr_t addr)
__asm __volatile("sfence.vma %0" :: "r" (addr) : "memory");
}
+#define rdcycle() csr_read64(cycle)
+#define rdtime() csr_read64(time)
+#define rdinstret() csr_read64(instret)
+#define rdhpmcounter(n) csr_read64(hpmcounter##n)
+
#define cpufunc_nullop() riscv_nullop()
void riscv_nullop(void);
diff --git a/sys/riscv/include/riscvreg.h b/sys/riscv/include/riscvreg.h
index fae70d9e0441..12e4a8fbbefa 100644
--- a/sys/riscv/include/riscvreg.h
+++ b/sys/riscv/include/riscvreg.h
@@ -223,4 +223,23 @@
val; \
})
+#if __riscv_xlen == 32
+#define csr_read64(csr) \
+({ uint64_t val; \
+ uint32_t high, low; \
+ __asm __volatile("1: " \
+ "csrr t0, " #csr "h\n" \
+ "csrr %0, " #csr "\n" \
+ "csrr %1, " #csr "h\n" \
+ "bne t0, %1, 1b" \
+ : "=r" (low), "=r" (high) \
+ : \
+ : "t0"); \
+ val = (low | ((uint64_t)high << 32)); \
+ val; \
+})
+#else
+#define csr_read64(csr) ((uint64_t)csr_read(csr))
+#endif
+
#endif /* !_MACHINE_RISCVREG_H_ */
diff --git a/sys/sys/blist.h b/sys/sys/blist.h
index 22d834f71544..595d3477aa08 100644
--- a/sys/sys/blist.h
+++ b/sys/sys/blist.h
@@ -73,22 +73,20 @@ typedef uint64_t u_daddr_t; /* unsigned disk address */
*/
typedef struct blmeta {
- union {
- daddr_t bmu_avail; /* space available under us */
- u_daddr_t bmu_bitmap; /* bitmap if we are a leaf */
- } u;
+ u_daddr_t bm_bitmap; /* bitmap if we are a leaf */
daddr_t bm_bighint; /* biggest contiguous block hint*/
} blmeta_t;
typedef struct blist {
daddr_t bl_blocks; /* area of coverage */
+ daddr_t bl_avail; /* # available blocks */
u_daddr_t bl_radix; /* coverage radix */
daddr_t bl_cursor; /* next-fit search starts at */
blmeta_t bl_root[1]; /* root of radix tree */
} *blist_t;
-#define BLIST_META_RADIX 16
#define BLIST_BMAP_RADIX (sizeof(u_daddr_t)*8)
+#define BLIST_META_RADIX BLIST_BMAP_RADIX
#define BLIST_MAX_ALLOC BLIST_BMAP_RADIX
diff --git a/sys/sys/epoch.h b/sys/sys/epoch.h
index 8d05c81e964b..3ed67a775625 100644
--- a/sys/sys/epoch.h
+++ b/sys/sys/epoch.h
@@ -29,10 +29,17 @@
#ifndef _SYS_EPOCH_H_
#define _SYS_EPOCH_H_
+
+struct epoch_context {
+ void *data[2];
+} __aligned(sizeof(void *));
+
+typedef struct epoch_context *epoch_context_t;
+
#ifdef _KERNEL
#include <sys/lock.h>
#include <sys/pcpu.h>
-#endif
+#include <ck_epoch.h>
struct epoch;
typedef struct epoch *epoch_t;
@@ -43,22 +50,19 @@ typedef struct epoch *epoch_t;
extern epoch_t global_epoch;
extern epoch_t global_epoch_preempt;
-struct epoch_context {
- void *data[2];
-} __aligned(sizeof(void *));
-
-typedef struct epoch_context *epoch_context_t;
-
-
struct epoch_tracker {
- void *datap[3];
-#ifdef EPOCH_TRACKER_DEBUG
- int datai[5];
-#else
- int datai[1];
+#ifdef EPOCH_TRACKER_DEBUG
+#define EPOCH_MAGIC0 0xFADECAFEF00DD00D
+#define EPOCH_MAGIC1 0xBADDBABEDEEDFEED
+ uint64_t et_magic_pre;
+#endif
+ TAILQ_ENTRY(epoch_tracker) et_link;
+ struct thread *et_td;
+ ck_epoch_section_t et_section;
+#ifdef EPOCH_TRACKER_DEBUG
+ uint64_t et_magic_post;
#endif
} __aligned(sizeof(void *));
-
typedef struct epoch_tracker *epoch_tracker_t;
epoch_t epoch_alloc(int flags);
@@ -68,26 +72,18 @@ void epoch_wait_preempt(epoch_t epoch);
void epoch_call(epoch_t epoch, epoch_context_t ctx, void (*callback) (epoch_context_t));
int in_epoch(epoch_t epoch);
int in_epoch_verbose(epoch_t epoch, int dump_onfail);
-#ifdef _KERNEL
DPCPU_DECLARE(int, epoch_cb_count);
DPCPU_DECLARE(struct grouptask, epoch_cb_task);
#define EPOCH_MAGIC0 0xFADECAFEF00DD00D
#define EPOCH_MAGIC1 0xBADDBABEDEEDFEED
-void epoch_enter_preempt_KBI(epoch_t epoch, epoch_tracker_t et);
-void epoch_exit_preempt_KBI(epoch_t epoch, epoch_tracker_t et);
-void epoch_enter_KBI(epoch_t epoch);
-void epoch_exit_KBI(epoch_t epoch);
+void epoch_enter_preempt(epoch_t epoch, epoch_tracker_t et);
+void epoch_exit_preempt(epoch_t epoch, epoch_tracker_t et);
+void epoch_enter(epoch_t epoch);
+void epoch_exit(epoch_t epoch);
+void epoch_thread_init(struct thread *);
+void epoch_thread_fini(struct thread *);
-#if defined(KLD_MODULE) && !defined(KLD_TIED)
-#define epoch_enter_preempt(e, t) epoch_enter_preempt_KBI((e), (t))
-#define epoch_exit_preempt(e, t) epoch_exit_preempt_KBI((e), (t))
-#define epoch_enter(e) epoch_enter_KBI((e))
-#define epoch_exit(e) epoch_exit_KBI((e))
-#else
-#include <sys/epoch_private.h>
-#endif /* KLD_MODULE */
-
-#endif /* _KERNEL */
-#endif
+#endif /* _KERNEL */
+#endif /* _SYS_EPOCH_H_ */
diff --git a/sys/sys/epoch_private.h b/sys/sys/epoch_private.h
deleted file mode 100644
index f475ca3aa200..000000000000
--- a/sys/sys/epoch_private.h
+++ /dev/null
@@ -1,211 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (c) 2018, Matthew Macy <mmacy@freebsd.org>
- *
- * 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$
- */
-
-#ifndef _SYS_EPOCH_PRIVATE_H_
-#define _SYS_EPOCH_PRIVATE_H_
-#ifndef _KERNEL
-#error "no user serviceable parts"
-#else
-#include <ck_epoch.h>
-#include <sys/kpilite.h>
-
-#include <sys/mutex.h>
-
-extern void epoch_adjust_prio(struct thread *td, u_char prio);
-#ifndef _SYS_SYSTM_H_
-extern void critical_exit_preempt(void);
-#endif
-
-#ifdef __amd64__
-#define EPOCH_ALIGN CACHE_LINE_SIZE*2
-#else
-#define EPOCH_ALIGN CACHE_LINE_SIZE
-#endif
-
-/*
- * Standalone (_sa) routines for thread state manipulation
- */
-static __inline void
-critical_enter_sa(void *tdarg)
-{
- struct thread_lite *td;
-
- td = tdarg;
- td->td_critnest++;
- __compiler_membar();
-}
-
-static __inline void
-critical_exit_sa(void *tdarg)
-{
- struct thread_lite *td;
-
- td = tdarg;
- MPASS(td->td_critnest > 0);
- __compiler_membar();
- td->td_critnest--;
- __compiler_membar();
- if (__predict_false(td->td_owepreempt != 0))
- critical_exit_preempt();
-}
-
-typedef struct epoch_thread {
-#ifdef EPOCH_TRACKER_DEBUG
- uint64_t et_magic_pre;
-#endif
- TAILQ_ENTRY(epoch_thread) et_link; /* Epoch queue. */
- struct thread *et_td; /* pointer to thread in section */
- ck_epoch_section_t et_section; /* epoch section object */
-#ifdef EPOCH_TRACKER_DEBUG
- uint64_t et_magic_post;
-#endif
-} *epoch_thread_t;
-TAILQ_HEAD (epoch_tdlist, epoch_thread);
-
-typedef struct epoch_record {
- ck_epoch_record_t er_read_record;
- ck_epoch_record_t er_write_record;
- volatile struct epoch_tdlist er_tdlist;
- volatile uint32_t er_gen;
- uint32_t er_cpuid;
-} __aligned(EPOCH_ALIGN) *epoch_record_t;
-
-struct epoch {
- struct ck_epoch e_epoch __aligned(EPOCH_ALIGN);
- epoch_record_t e_pcpu_record;
- int e_idx;
- int e_flags;
-};
-
-static epoch_record_t
-epoch_currecord(epoch_t epoch)
-{
- return zpcpu_get_cpu(epoch->e_pcpu_record, curcpu);
-}
-
-#define INIT_CHECK(epoch) \
- do { \
- if (__predict_false((epoch) == NULL)) \
- return; \
- } while (0)
-
-static __inline void
-epoch_enter_preempt(epoch_t epoch, epoch_tracker_t et)
-{
- struct epoch_record *er;
- struct epoch_thread *etd;
- struct thread_lite *td;
-
- MPASS(cold || epoch != NULL);
- INIT_CHECK(epoch);
- etd = (void *)et;
- MPASS(epoch->e_flags & EPOCH_PREEMPT);
-#ifdef EPOCH_TRACKER_DEBUG
- etd->et_magic_pre = EPOCH_MAGIC0;
- etd->et_magic_post = EPOCH_MAGIC1;
-#endif
- td = (struct thread_lite *)curthread;
- etd->et_td = (void*)td;
- td->td_epochnest++;
- critical_enter_sa(td);
- sched_pin_lite(td);
-
- td->td_pre_epoch_prio = td->td_priority;
- er = epoch_currecord(epoch);
- TAILQ_INSERT_TAIL(&er->er_tdlist, etd, et_link);
- ck_epoch_begin(&er->er_read_record, (ck_epoch_section_t *)&etd->et_section);
- critical_exit_sa(td);
-}
-
-static __inline void
-epoch_enter(epoch_t epoch)
-{
- struct thread_lite *td;
- epoch_record_t er;
-
- MPASS(cold || epoch != NULL);
- INIT_CHECK(epoch);
- td = (struct thread_lite *)curthread;
-
- td->td_epochnest++;
- critical_enter_sa(td);
- er = epoch_currecord(epoch);
- ck_epoch_begin(&er->er_read_record, NULL);
-}
-
-static __inline void
-epoch_exit_preempt(epoch_t epoch, epoch_tracker_t et)
-{
- struct epoch_record *er;
- struct epoch_thread *etd;
- struct thread_lite *td;
-
- INIT_CHECK(epoch);
- td = (struct thread_lite *)curthread;
- critical_enter_sa(td);
- sched_unpin_lite(td);
- MPASS(td->td_epochnest);
- td->td_epochnest--;
- er = epoch_currecord(epoch);
- MPASS(epoch->e_flags & EPOCH_PREEMPT);
- etd = (void *)et;
- MPASS(etd != NULL);
- MPASS(etd->et_td == (struct thread *)td);
-#ifdef EPOCH_TRACKER_DEBUG
- MPASS(etd->et_magic_pre == EPOCH_MAGIC0);
- MPASS(etd->et_magic_post == EPOCH_MAGIC1);
- etd->et_magic_pre = 0;
- etd->et_magic_post = 0;
-#endif
- etd->et_td = (void*)0xDEADBEEF;
- ck_epoch_end(&er->er_read_record,
- (ck_epoch_section_t *)&etd->et_section);
- TAILQ_REMOVE(&er->er_tdlist, etd, et_link);
- er->er_gen++;
- if (__predict_false(td->td_pre_epoch_prio != td->td_priority))
- epoch_adjust_prio((struct thread *)td, td->td_pre_epoch_prio);
- critical_exit_sa(td);
-}
-
-static __inline void
-epoch_exit(epoch_t epoch)
-{
- struct thread_lite *td;
- epoch_record_t er;
-
- INIT_CHECK(epoch);
- td = (struct thread_lite *)curthread;
- MPASS(td->td_epochnest);
- td->td_epochnest--;
- er = epoch_currecord(epoch);
- ck_epoch_end(&er->er_read_record, NULL);
- critical_exit_sa(td);
-}
-#endif /* _KERNEL */
-#endif /* _SYS_EPOCH_PRIVATE_H_ */
diff --git a/sys/sys/proc.h b/sys/sys/proc.h
index d5351dd043c1..b43758c4e568 100644
--- a/sys/sys/proc.h
+++ b/sys/sys/proc.h
@@ -193,6 +193,7 @@ struct trapframe;
struct turnstile;
struct vm_map;
struct vm_map_entry;
+struct epoch_tracker;
/*
* XXX: Does this belong in resource.h or resourcevar.h instead?
@@ -360,6 +361,7 @@ struct thread {
int td_lastcpu; /* (t) Last cpu we were on. */
int td_oncpu; /* (t) Which cpu we are on. */
void *td_lkpi_task; /* LinuxKPI task struct pointer */
+ struct epoch_tracker *td_et; /* (k) compat KPI spare tracker */
int td_pmcpend;
};
diff --git a/sys/ufs/ffs/ffs_extern.h b/sys/ufs/ffs/ffs_extern.h
index 6b8e708f7371..c2f6c91bcc4b 100644
--- a/sys/ufs/ffs/ffs_extern.h
+++ b/sys/ufs/ffs/ffs_extern.h
@@ -82,7 +82,7 @@ int ffs_getcg(struct fs *, struct vnode *, u_int, struct buf **,
struct cg **);
int ffs_isblock(struct fs *, u_char *, ufs1_daddr_t);
int ffs_isfreeblock(struct fs *, u_char *, ufs1_daddr_t);
-void ffs_load_inode(struct buf *, struct inode *, struct fs *, ino_t);
+int ffs_load_inode(struct buf *, struct inode *, struct fs *, ino_t);
void ffs_oldfscompat_write(struct fs *, struct ufsmount *);
int ffs_own_mount(const struct mount *mp);
int ffs_reallocblks(struct vop_reallocblks_args *);
diff --git a/sys/ufs/ffs/ffs_inode.c b/sys/ufs/ffs/ffs_inode.c
index a1be71511434..d146d14980c3 100644
--- a/sys/ufs/ffs/ffs_inode.c
+++ b/sys/ufs/ffs/ffs_inode.c
@@ -148,12 +148,18 @@ loop:
if (I_IS_UFS1(ip)) {
*((struct ufs1_dinode *)bp->b_data +
ino_to_fsbo(fs, ip->i_number)) = *ip->i_din1;
- /* XXX: FIX? The entropy here is desirable, but the harvesting may be expensive */
+ /*
+ * XXX: FIX? The entropy here is desirable,
+ * but the harvesting may be expensive
+ */
random_harvest_queue(&(ip->i_din1), sizeof(ip->i_din1), RANDOM_FS_ATIME);
} else {
*((struct ufs2_dinode *)bp->b_data +
ino_to_fsbo(fs, ip->i_number)) = *ip->i_din2;
- /* XXX: FIX? The entropy here is desirable, but the harvesting may be expensive */
+ /*
+ * XXX: FIX? The entropy here is desirable,
+ * but the harvesting may be expensive
+ */
random_harvest_queue(&(ip->i_din2), sizeof(ip->i_din2), RANDOM_FS_ATIME);
}
if (waitfor)
diff --git a/sys/ufs/ffs/ffs_snapshot.c b/sys/ufs/ffs/ffs_snapshot.c
index 4453c59517df..09b1d4982c49 100644
--- a/sys/ufs/ffs/ffs_snapshot.c
+++ b/sys/ufs/ffs/ffs_snapshot.c
@@ -1333,12 +1333,12 @@ expunge_ufs2(snapvp, cancelip, fs, acctfunc, expungetype, clearmode)
*/
dip = (struct ufs2_dinode *)bp->b_data +
ino_to_fsbo(fs, cancelip->i_number);
- if (clearmode || cancelip->i_effnlink == 0)
- dip->di_mode = 0;
dip->di_size = 0;
dip->di_blocks = 0;
dip->di_flags &= ~SF_SNAPSHOT;
bzero(&dip->di_db[0], (UFS_NDADDR + UFS_NIADDR) * sizeof(ufs2_daddr_t));
+ if (clearmode || cancelip->i_effnlink == 0)
+ dip->di_mode = 0;
bdwrite(bp);
/*
* Now go through and expunge all the blocks in the file
diff --git a/sys/ufs/ffs/ffs_softdep.c b/sys/ufs/ffs/ffs_softdep.c
index dcc72b2fdfd3..3fe9e205f858 100644
--- a/sys/ufs/ffs/ffs_softdep.c
+++ b/sys/ufs/ffs/ffs_softdep.c
@@ -6698,12 +6698,13 @@ softdep_journal_freeblocks(ip, cred, length, flags)
if (bp->b_bufsize == fs->fs_bsize)
bp->b_flags |= B_CLUSTEROK;
softdep_update_inodeblock(ip, bp, 0);
- if (ump->um_fstype == UFS1)
+ if (ump->um_fstype == UFS1) {
*((struct ufs1_dinode *)bp->b_data +
ino_to_fsbo(fs, ip->i_number)) = *ip->i_din1;
- else
+ } else {
*((struct ufs2_dinode *)bp->b_data +
ino_to_fsbo(fs, ip->i_number)) = *ip->i_din2;
+ }
ACQUIRE_LOCK(ump);
(void) inodedep_lookup(mp, ip->i_number, DEPALLOC, &inodedep);
if ((inodedep->id_state & IOSTARTED) != 0)
@@ -9640,6 +9641,7 @@ static void
clear_unlinked_inodedep(inodedep)
struct inodedep *inodedep;
{
+ struct ufs2_dinode *dip;
struct ufsmount *ump;
struct inodedep *idp;
struct inodedep *idn;
@@ -9743,12 +9745,14 @@ clear_unlinked_inodedep(inodedep)
ffs_oldfscompat_write((struct fs *)bp->b_data, ump);
softdep_setup_sbupdate(ump, (struct fs *)bp->b_data,
bp);
- } else if (fs->fs_magic == FS_UFS1_MAGIC)
+ } else if (fs->fs_magic == FS_UFS1_MAGIC) {
((struct ufs1_dinode *)bp->b_data +
ino_to_fsbo(fs, pino))->di_freelink = nino;
- else
- ((struct ufs2_dinode *)bp->b_data +
- ino_to_fsbo(fs, pino))->di_freelink = nino;
+ } else {
+ dip = (struct ufs2_dinode *)bp->b_data +
+ ino_to_fsbo(fs, pino);
+ dip->di_freelink = nino;
+ }
/*
* If the bwrite fails we have no recourse to recover. The
* filesystem is corrupted already.
diff --git a/sys/ufs/ffs/ffs_subr.c b/sys/ufs/ffs/ffs_subr.c
index de70a3f84283..541d44c887db 100644
--- a/sys/ufs/ffs/ffs_subr.c
+++ b/sys/ufs/ffs/ffs_subr.c
@@ -108,31 +108,35 @@ ffs_blkatoff(struct vnode *vp, off_t offset, char **res, struct buf **bpp)
* Load up the contents of an inode and copy the appropriate pieces
* to the incore copy.
*/
-void
+int
ffs_load_inode(struct buf *bp, struct inode *ip, struct fs *fs, ino_t ino)
{
+ struct ufs1_dinode *dip1;
+ struct ufs2_dinode *dip2;
if (I_IS_UFS1(ip)) {
- *ip->i_din1 =
+ dip1 = ip->i_din1;
+ *dip1 =
*((struct ufs1_dinode *)bp->b_data + ino_to_fsbo(fs, ino));
- ip->i_mode = ip->i_din1->di_mode;
- ip->i_nlink = ip->i_din1->di_nlink;
- ip->i_size = ip->i_din1->di_size;
- ip->i_flags = ip->i_din1->di_flags;
- ip->i_gen = ip->i_din1->di_gen;
- ip->i_uid = ip->i_din1->di_uid;
- ip->i_gid = ip->i_din1->di_gid;
- } else {
- *ip->i_din2 =
- *((struct ufs2_dinode *)bp->b_data + ino_to_fsbo(fs, ino));
- ip->i_mode = ip->i_din2->di_mode;
- ip->i_nlink = ip->i_din2->di_nlink;
- ip->i_size = ip->i_din2->di_size;
- ip->i_flags = ip->i_din2->di_flags;
- ip->i_gen = ip->i_din2->di_gen;
- ip->i_uid = ip->i_din2->di_uid;
- ip->i_gid = ip->i_din2->di_gid;
+ ip->i_mode = dip1->di_mode;
+ ip->i_nlink = dip1->di_nlink;
+ ip->i_size = dip1->di_size;
+ ip->i_flags = dip1->di_flags;
+ ip->i_gen = dip1->di_gen;
+ ip->i_uid = dip1->di_uid;
+ ip->i_gid = dip1->di_gid;
+ return (0);
}
+ dip2 = ip->i_din2;
+ *dip2 = *((struct ufs2_dinode *)bp->b_data + ino_to_fsbo(fs, ino));
+ ip->i_mode = dip2->di_mode;
+ ip->i_nlink = dip2->di_nlink;
+ ip->i_size = dip2->di_size;
+ ip->i_flags = dip2->di_flags;
+ ip->i_gen = dip2->di_gen;
+ ip->i_uid = dip2->di_uid;
+ ip->i_gid = dip2->di_gid;
+ return (0);
}
#endif /* KERNEL */
diff --git a/sys/ufs/ffs/ffs_vfsops.c b/sys/ufs/ffs/ffs_vfsops.c
index b69dd20da113..7ecaae231f07 100644
--- a/sys/ufs/ffs/ffs_vfsops.c
+++ b/sys/ufs/ffs/ffs_vfsops.c
@@ -740,16 +740,19 @@ loop:
bread(devvp, fsbtodb(fs, ino_to_fsba(fs, ip->i_number)),
(int)fs->fs_bsize, NOCRED, &bp);
if (error) {
- VOP_UNLOCK(vp, 0);
- vrele(vp);
+ vput(vp);
+ MNT_VNODE_FOREACH_ALL_ABORT(mp, mvp);
+ return (error);
+ }
+ if ((error = ffs_load_inode(bp, ip, fs, ip->i_number)) != 0) {
+ brelse(bp);
+ vput(vp);
MNT_VNODE_FOREACH_ALL_ABORT(mp, mvp);
return (error);
}
- ffs_load_inode(bp, ip, fs, ip->i_number);
ip->i_effnlink = ip->i_nlink;
brelse(bp);
- VOP_UNLOCK(vp, 0);
- vrele(vp);
+ vput(vp);
}
return (0);
}
@@ -1729,7 +1732,12 @@ ffs_vgetf(mp, ino, flags, vpp, ffs_flags)
ip->i_din1 = uma_zalloc(uma_ufs1, M_WAITOK);
else
ip->i_din2 = uma_zalloc(uma_ufs2, M_WAITOK);
- ffs_load_inode(bp, ip, fs, ino);
+ if ((error = ffs_load_inode(bp, ip, fs, ino)) != 0) {
+ bqrelse(bp);
+ vput(vp);
+ *vpp = NULL;
+ return (error);
+ }
if (DOINGSOFTDEP(vp))
softdep_load_inodeblock(ip);
else
diff --git a/sys/vm/uma_core.c b/sys/vm/uma_core.c
index 9db39ea2ac80..7d14586a31cd 100644
--- a/sys/vm/uma_core.c
+++ b/sys/vm/uma_core.c
@@ -459,6 +459,36 @@ bucket_zone_drain(void)
zone_drain(ubz->ubz_zone);
}
+static uma_bucket_t
+zone_try_fetch_bucket(uma_zone_t zone, uma_zone_domain_t zdom, const bool ws)
+{
+ uma_bucket_t bucket;
+
+ ZONE_LOCK_ASSERT(zone);
+
+ if ((bucket = LIST_FIRST(&zdom->uzd_buckets)) != NULL) {
+ MPASS(zdom->uzd_nitems >= bucket->ub_cnt);
+ LIST_REMOVE(bucket, ub_link);
+ zdom->uzd_nitems -= bucket->ub_cnt;
+ if (ws && zdom->uzd_imin > zdom->uzd_nitems)
+ zdom->uzd_imin = zdom->uzd_nitems;
+ }
+ return (bucket);
+}
+
+static void
+zone_put_bucket(uma_zone_t zone, uma_zone_domain_t zdom, uma_bucket_t bucket,
+ const bool ws)
+{
+
+ ZONE_LOCK_ASSERT(zone);
+
+ LIST_INSERT_HEAD(&zdom->uzd_buckets, bucket, ub_link);
+ zdom->uzd_nitems += bucket->ub_cnt;
+ if (ws && zdom->uzd_imax < zdom->uzd_nitems)
+ zdom->uzd_imax = zdom->uzd_nitems;
+}
+
static void
zone_log_warning(uma_zone_t zone)
{
@@ -509,6 +539,23 @@ uma_timeout(void *unused)
}
/*
+ * Update the working set size estimate for the zone's bucket cache.
+ * The constants chosen here are somewhat arbitrary. With an update period of
+ * 20s (UMA_TIMEOUT), this estimate is dominated by zone activity over the
+ * last 100s.
+ */
+static void
+zone_domain_update_wss(uma_zone_domain_t zdom)
+{
+ long wss;
+
+ MPASS(zdom->uzd_imax >= zdom->uzd_imin);
+ wss = zdom->uzd_imax - zdom->uzd_imin;
+ zdom->uzd_imax = zdom->uzd_imin = zdom->uzd_nitems;
+ zdom->uzd_wss = (3 * wss + 2 * zdom->uzd_wss) / 5;
+}
+
+/*
* Routine to perform timeout driven calculations. This expands the
* hashes and does per cpu statistics aggregation.
*
@@ -560,8 +607,14 @@ keg_timeout(uma_keg_t keg)
static void
zone_timeout(uma_zone_t zone)
{
+ int i;
zone_foreach_keg(zone, &keg_timeout);
+
+ ZONE_LOCK(zone);
+ for (i = 0; i < vm_ndomains; i++)
+ zone_domain_update_wss(&zone->uz_domain[i]);
+ ZONE_UNLOCK(zone);
}
/*
@@ -772,16 +825,16 @@ cache_drain_safe_cpu(uma_zone_t zone)
cache = &zone->uz_cpu[curcpu];
if (cache->uc_allocbucket) {
if (cache->uc_allocbucket->ub_cnt != 0)
- LIST_INSERT_HEAD(&zone->uz_domain[domain].uzd_buckets,
- cache->uc_allocbucket, ub_link);
+ zone_put_bucket(zone, &zone->uz_domain[domain],
+ cache->uc_allocbucket, false);
else
b1 = cache->uc_allocbucket;
cache->uc_allocbucket = NULL;
}
if (cache->uc_freebucket) {
if (cache->uc_freebucket->ub_cnt != 0)
- LIST_INSERT_HEAD(&zone->uz_domain[domain].uzd_buckets,
- cache->uc_freebucket, ub_link);
+ zone_put_bucket(zone, &zone->uz_domain[domain],
+ cache->uc_freebucket, false);
else
b2 = cache->uc_freebucket;
cache->uc_freebucket = NULL;
@@ -844,8 +897,8 @@ bucket_cache_drain(uma_zone_t zone)
*/
for (i = 0; i < vm_ndomains; i++) {
zdom = &zone->uz_domain[i];
- while ((bucket = LIST_FIRST(&zdom->uzd_buckets)) != NULL) {
- LIST_REMOVE(bucket, ub_link);
+ while ((bucket = zone_try_fetch_bucket(zone, zdom, false)) !=
+ NULL) {
ZONE_UNLOCK(zone);
bucket_drain(zone, bucket);
bucket_free(zone, bucket, NULL);
@@ -2523,11 +2576,9 @@ zalloc_start:
zdom = &zone->uz_domain[0];
else
zdom = &zone->uz_domain[domain];
- if ((bucket = LIST_FIRST(&zdom->uzd_buckets)) != NULL) {
+ if ((bucket = zone_try_fetch_bucket(zone, zdom, true)) != NULL) {
KASSERT(bucket->ub_cnt != 0,
("uma_zalloc_arg: Returning an empty bucket."));
-
- LIST_REMOVE(bucket, ub_link);
cache->uc_allocbucket = bucket;
ZONE_UNLOCK(zone);
goto zalloc_start;
@@ -2556,6 +2607,7 @@ zalloc_start:
critical_enter();
cpu = curcpu;
cache = &zone->uz_cpu[cpu];
+
/*
* See if we lost the race or were migrated. Cache the
* initialized bucket to make this less likely or claim
@@ -2565,6 +2617,7 @@ zalloc_start:
((zone->uz_flags & UMA_ZONE_NUMA) == 0 ||
domain == PCPU_GET(domain))) {
cache->uc_allocbucket = bucket;
+ zdom->uzd_imax += bucket->ub_cnt;
} else if ((zone->uz_flags & UMA_ZONE_NOBUCKETCACHE) != 0) {
critical_exit();
ZONE_UNLOCK(zone);
@@ -2572,7 +2625,7 @@ zalloc_start:
bucket_free(zone, bucket, udata);
goto zalloc_restart;
} else
- LIST_INSERT_HEAD(&zdom->uzd_buckets, bucket, ub_link);
+ zone_put_bucket(zone, zdom, bucket, false);
ZONE_UNLOCK(zone);
goto zalloc_start;
}
@@ -3200,7 +3253,7 @@ zfree_start:
bucket_free(zone, bucket, udata);
goto zfree_restart;
} else
- LIST_INSERT_HEAD(&zdom->uzd_buckets, bucket, ub_link);
+ zone_put_bucket(zone, zdom, bucket, true);
}
/*
@@ -3649,6 +3702,7 @@ uma_reclaim_locked(bool kmem_danger)
cache_drain_safe(NULL);
zone_foreach(zone_drain);
}
+
/*
* Some slabs may have been freed but this zone will be visited early
* we visit again so that we can free pages that are empty once other
@@ -3882,7 +3936,7 @@ uma_print_zone(uma_zone_t zone)
* directly so that we don't have to.
*/
static void
-uma_zone_sumstat(uma_zone_t z, int *cachefreep, uint64_t *allocsp,
+uma_zone_sumstat(uma_zone_t z, long *cachefreep, uint64_t *allocsp,
uint64_t *freesp, uint64_t *sleepsp)
{
uma_cache_t cache;
@@ -3937,7 +3991,6 @@ sysctl_vm_zone_stats(SYSCTL_HANDLER_ARGS)
struct uma_stream_header ush;
struct uma_type_header uth;
struct uma_percpu_stat *ups;
- uma_bucket_t bucket;
uma_zone_domain_t zdom;
struct sbuf sbuf;
uma_cache_t cache;
@@ -3997,9 +4050,7 @@ sysctl_vm_zone_stats(SYSCTL_HANDLER_ARGS)
for (i = 0; i < vm_ndomains; i++) {
zdom = &z->uz_domain[i];
- LIST_FOREACH(bucket, &zdom->uzd_buckets,
- ub_link)
- uth.uth_zone_free += bucket->ub_cnt;
+ uth.uth_zone_free += zdom->uzd_nitems;
}
uth.uth_allocs = z->uz_allocs;
uth.uth_frees = z->uz_frees;
@@ -4199,12 +4250,11 @@ uma_dbg_free(uma_zone_t zone, uma_slab_t slab, void *item)
#ifdef DDB
DB_SHOW_COMMAND(uma, db_show_uma)
{
- uma_bucket_t bucket;
uma_keg_t kz;
uma_zone_t z;
- uma_zone_domain_t zdom;
uint64_t allocs, frees, sleeps;
- int cachefree, i;
+ long cachefree;
+ int i;
db_printf("%18s %8s %8s %8s %12s %8s %8s\n", "Zone", "Size", "Used",
"Free", "Requests", "Sleeps", "Bucket");
@@ -4221,13 +4271,10 @@ DB_SHOW_COMMAND(uma, db_show_uma)
if (!((z->uz_flags & UMA_ZONE_SECONDARY) &&
(LIST_FIRST(&kz->uk_zones) != z)))
cachefree += kz->uk_free;
- for (i = 0; i < vm_ndomains; i++) {
- zdom = &z->uz_domain[i];
- LIST_FOREACH(bucket, &zdom->uzd_buckets,
- ub_link)
- cachefree += bucket->ub_cnt;
- }
- db_printf("%18s %8ju %8jd %8d %12ju %8ju %8u\n",
+ for (i = 0; i < vm_ndomains; i++)
+ cachefree += z->uz_domain[i].uzd_nitems;
+
+ db_printf("%18s %8ju %8jd %8ld %12ju %8ju %8u\n",
z->uz_name, (uintmax_t)kz->uk_size,
(intmax_t)(allocs - frees), cachefree,
(uintmax_t)allocs, sleeps, z->uz_count);
@@ -4239,22 +4286,18 @@ DB_SHOW_COMMAND(uma, db_show_uma)
DB_SHOW_COMMAND(umacache, db_show_umacache)
{
- uma_bucket_t bucket;
uma_zone_t z;
- uma_zone_domain_t zdom;
uint64_t allocs, frees;
- int cachefree, i;
+ long cachefree;
+ int i;
db_printf("%18s %8s %8s %8s %12s %8s\n", "Zone", "Size", "Used", "Free",
"Requests", "Bucket");
LIST_FOREACH(z, &uma_cachezones, uz_link) {
uma_zone_sumstat(z, &cachefree, &allocs, &frees, NULL);
- for (i = 0; i < vm_ndomains; i++) {
- zdom = &z->uz_domain[i];
- LIST_FOREACH(bucket, &zdom->uzd_buckets, ub_link)
- cachefree += bucket->ub_cnt;
- }
- db_printf("%18s %8ju %8jd %8d %12ju %8u\n",
+ for (i = 0; i < vm_ndomains; i++)
+ cachefree += z->uz_domain[i].uzd_nitems;
+ db_printf("%18s %8ju %8jd %8ld %12ju %8u\n",
z->uz_name, (uintmax_t)z->uz_size,
(intmax_t)(allocs - frees), cachefree,
(uintmax_t)allocs, z->uz_count);
diff --git a/sys/vm/uma_int.h b/sys/vm/uma_int.h
index 5b28df3701bf..a97f51734ef6 100644
--- a/sys/vm/uma_int.h
+++ b/sys/vm/uma_int.h
@@ -304,6 +304,10 @@ typedef struct uma_klink *uma_klink_t;
struct uma_zone_domain {
LIST_HEAD(,uma_bucket) uzd_buckets; /* full buckets */
+ long uzd_nitems; /* total item count */
+ long uzd_imax; /* maximum item count this period */
+ long uzd_imin; /* minimum item count this period */
+ long uzd_wss; /* working set size estimate */
};
typedef struct uma_zone_domain * uma_zone_domain_t;
@@ -423,11 +427,12 @@ void uma_large_free(uma_slab_t slab);
mtx_init(&(z)->uz_lock, (z)->uz_name, \
"UMA zone", MTX_DEF | MTX_DUPOK); \
} while (0)
-
+
#define ZONE_LOCK(z) mtx_lock((z)->uz_lockptr)
#define ZONE_TRYLOCK(z) mtx_trylock((z)->uz_lockptr)
#define ZONE_UNLOCK(z) mtx_unlock((z)->uz_lockptr)
#define ZONE_LOCK_FINI(z) mtx_destroy(&(z)->uz_lock)
+#define ZONE_LOCK_ASSERT(z) mtx_assert((z)->uz_lockptr, MA_OWNED)
/*
* Find a slab within a hash table. This is used for OFFPAGE zones to lookup
diff --git a/sys/x86/include/x86_var.h b/sys/x86/include/x86_var.h
index 286c01261f0f..8f53b41fd197 100644
--- a/sys/x86/include/x86_var.h
+++ b/sys/x86/include/x86_var.h
@@ -129,6 +129,7 @@ void dump_drop_page(vm_paddr_t);
void finishidentcpu(void);
void identify_cpu1(void);
void identify_cpu2(void);
+void identify_cpu_fixup_bsp(void);
void identify_hypervisor(void);
void initializecpu(void);
void initializecpucache(void);
diff --git a/sys/x86/x86/identcpu.c b/sys/x86/x86/identcpu.c
index 8e406f053baa..56186b2f3ba4 100644
--- a/sys/x86/x86/identcpu.c
+++ b/sys/x86/x86/identcpu.c
@@ -1467,6 +1467,19 @@ identify_cpu2(void)
}
}
+void
+identify_cpu_fixup_bsp(void)
+{
+ u_int regs[4];
+
+ cpu_vendor_id = find_cpu_vendor_id();
+
+ if (fix_cpuid()) {
+ do_cpuid(0, regs);
+ cpu_high = regs[0];
+ }
+}
+
/*
* Final stage of CPU identification.
*/
@@ -1478,12 +1491,7 @@ finishidentcpu(void)
u_char ccr3;
#endif
- cpu_vendor_id = find_cpu_vendor_id();
-
- if (fix_cpuid()) {
- do_cpuid(0, regs);
- cpu_high = regs[0];
- }
+ identify_cpu_fixup_bsp();
if (cpu_high >= 5 && (cpu_feature2 & CPUID2_MON) != 0) {
do_cpuid(5, regs);