Change compute node to worker node personality
This update replaced the compute personality & subfunction to worker, and updated internal and customer visible references. In addition, the compute-huge package has been renamed to worker-utils as it contains various scripts/services that used to affine running tasks or interface IRQ to specific CPUs. The worker_reserved.conf is now installed to /etc/platform. The cpu function 'VM' has also been renamed to 'Application'. Tests Performed: Non-containerized deployment AIO-SX: Sanity and Nightly automated test suite AIO-DX: Sanity and Nightly automated test suite 2+2 System: Sanity and Nightly automated test suite 2+2 System: Horizon Patch Orchestration Kubernetes deployment: AIO-SX: Create, delete, reboot and rebuild instances 2+2+2 System: worker nodes are unlock enable and no alarms Story: 2004022 Task: 27013 Change-Id: I0e0be6b3a6f25f7fb8edf64ea4326854513aa396 Signed-off-by: Tao Liu <tao.liu@windriver.com>
This commit is contained in:
6
utilities/worker-utils/.gitignore
vendored
Normal file
6
utilities/worker-utils/.gitignore
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
!.distro
|
||||
.distro/centos7/rpmbuild/RPMS
|
||||
.distro/centos7/rpmbuild/SRPMS
|
||||
.distro/centos7/rpmbuild/BUILD
|
||||
.distro/centos7/rpmbuild/BUILDROOT
|
||||
.distro/centos7/rpmbuild/SOURCES/worker-utils*tar.gz
|
||||
3
utilities/worker-utils/centos/build_srpm.data
Normal file
3
utilities/worker-utils/centos/build_srpm.data
Normal file
@@ -0,0 +1,3 @@
|
||||
SRC_DIR="worker-utils"
|
||||
COPY_LIST="$SRC_DIR/LICENSE"
|
||||
TIS_PATCH_VER=1
|
||||
55
utilities/worker-utils/centos/worker-utils.spec
Normal file
55
utilities/worker-utils/centos/worker-utils.spec
Normal file
@@ -0,0 +1,55 @@
|
||||
Summary: Initial worker node resource reservation and misc. utilities
|
||||
Name: worker-utils
|
||||
Version: 1.0
|
||||
Release: %{tis_patch_ver}%{?_tis_dist}
|
||||
License: Apache-2.0
|
||||
Group: base
|
||||
Packager: Wind River <info@windriver.com>
|
||||
URL: unknown
|
||||
Source0: %{name}-%{version}.tar.gz
|
||||
Source1: LICENSE
|
||||
|
||||
BuildRequires: systemd-devel
|
||||
Requires: systemd
|
||||
Requires: python
|
||||
Requires: /bin/systemctl
|
||||
|
||||
%description
|
||||
Initial worker node resource reservation and misc. utilities
|
||||
|
||||
%define local_bindir /usr/bin/
|
||||
%define local_etc_initd /etc/init.d/
|
||||
%define local_etc_platform /etc/platform/
|
||||
%define local_etc_goenabledd /etc/goenabled.d/
|
||||
|
||||
%define debug_package %{nil}
|
||||
|
||||
%prep
|
||||
%setup
|
||||
|
||||
%build
|
||||
make
|
||||
|
||||
%install
|
||||
make install BINDIR=%{buildroot}%{local_bindir} \
|
||||
INITDDIR=%{buildroot}%{local_etc_initd} \
|
||||
GOENABLEDDIR=%{buildroot}%{local_etc_goenabledd} \
|
||||
PLATFORMCONFDIR=%{buildroot}%{local_etc_platform} \
|
||||
SYSTEMDDIR=%{buildroot}%{_unitdir}
|
||||
|
||||
%post
|
||||
/bin/systemctl enable affine-platform.sh.service >/dev/null 2>&1
|
||||
|
||||
%clean
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
|
||||
%files
|
||||
|
||||
%defattr(-,root,root,-)
|
||||
|
||||
%{local_bindir}/*
|
||||
%{local_etc_initd}/*
|
||||
%{local_etc_goenabledd}/*
|
||||
%config(noreplace) %{local_etc_platform}/worker_reserved.conf
|
||||
|
||||
%{_unitdir}/affine-platform.sh.service
|
||||
202
utilities/worker-utils/worker-utils/LICENSE
Normal file
202
utilities/worker-utils/worker-utils/LICENSE
Normal file
@@ -0,0 +1,202 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
31
utilities/worker-utils/worker-utils/Makefile
Normal file
31
utilities/worker-utils/worker-utils/Makefile
Normal file
@@ -0,0 +1,31 @@
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
BINDIR ?= /usr/bin
|
||||
INITDDIR ?= /etc/init.d/
|
||||
GOENABLEDDIR ?= /etc/goenabled.d/
|
||||
PLATFORMCONFDIR ?= /etc/platform
|
||||
SYSTEMDDIR ?= /usr/lib/systemd/system/
|
||||
|
||||
all:
|
||||
python -m compileall topology.py
|
||||
|
||||
install:
|
||||
install -d -m 755 $(BINDIR)
|
||||
install -d -m 755 $(INITDDIR)
|
||||
install -d -m 755 $(GOENABLEDDIR)
|
||||
install -d -m 755 $(PLATFORMCONFDIR)
|
||||
install -d -m 755 $(SYSTEMDDIR)
|
||||
install -p -D -m 755 affine-platform.sh $(INITDDIR)/affine-platform.sh
|
||||
install -p -D -m 755 cpumap_functions.sh $(INITDDIR)/cpumap_functions.sh
|
||||
install -p -D -m 755 task_affinity_functions.sh $(INITDDIR)/task_affinity_functions.sh
|
||||
install -p -D -m 755 ps-sched.sh $(BINDIR)/ps-sched.sh
|
||||
install -p -D -m 755 topology.py $(BINDIR)/topology.py
|
||||
install -p -D -m 755 topology.pyc $(BINDIR)/topology.pyc
|
||||
install -p -D -m 755 affine-interrupts.sh $(BINDIR)/affine-interrupts.sh
|
||||
install -p -D -m 755 set-cpu-wakeup-latency.sh $(BINDIR)/set-cpu-wakeup-latency.sh
|
||||
install -p -D -m 755 topology $(BINDIR)/topology
|
||||
install -p -D -m 755 worker_reserved.conf $(PLATFORMCONFDIR)/worker_reserved.conf
|
||||
install -p -D -m 755 worker-goenabled.sh $(GOENABLEDDIR)/worker-goenabled.sh
|
||||
install -p -D -m 664 affine-platform.sh.service $(SYSTEMDDIR)/affine-platform.sh.service
|
||||
59
utilities/worker-utils/worker-utils/affine-interrupts.sh
Normal file
59
utilities/worker-utils/worker-utils/affine-interrupts.sh
Normal file
@@ -0,0 +1,59 @@
|
||||
#!/bin/bash
|
||||
################################################################################
|
||||
# Copyright (c) 2015-2016 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
################################################################################
|
||||
#
|
||||
# Purpose:
|
||||
# Affine the interface IRQ to specified cpulist.
|
||||
#
|
||||
# Usage: /usr/bin/affine-interrupts.sh interface cpulist
|
||||
#
|
||||
# Define minimal path
|
||||
PATH=/bin:/usr/bin:/usr/local/bin
|
||||
|
||||
# logger setup
|
||||
WHOAMI=`basename $0`
|
||||
LOG_FACILITY=user
|
||||
LOG_PRIORITY=info
|
||||
TMPLOG=/tmp/${WHOAMI}.log
|
||||
|
||||
# LOG() - generates log and puts in temporary file
|
||||
function LOG {
|
||||
logger -t "${0##*/}[$$]" -p ${LOG_FACILITY}.${LOG_PRIORITY} "$@"
|
||||
echo "${0##*/}[$$]" "$@" >> ${TMPLOG}
|
||||
}
|
||||
function INFO {
|
||||
MSG="INFO"
|
||||
LOG "${MSG} $@"
|
||||
}
|
||||
function ERROR {
|
||||
MSG="ERROR"
|
||||
LOG "${MSG} $@"
|
||||
}
|
||||
|
||||
if [ "$#" -ne 2 ]; then
|
||||
ERROR "Interface name and cpulist are required"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
interface=$1
|
||||
cpulist=$2
|
||||
|
||||
# Find PCI device matching interface, keep last matching device name
|
||||
dev=$(find /sys/devices -name "${interface}" | \
|
||||
perl -ne 'print $1 if /([[:xdigit:]]{4}:[[:xdigit:]]{2}:[[:xdigit:]]{2}\.[[:xdigit:]])\/[[:alpha:]]/;')
|
||||
|
||||
# Obtain all IRQs for this device
|
||||
irq=$(cat /sys/bus/pci/devices/${dev}/irq 2>/dev/null)
|
||||
msi_irqs=$(ls /sys/bus/pci/devices/${dev}/msi_irqs 2>/dev/null | xargs)
|
||||
|
||||
INFO $LINENO "affine ${interface} (dev:${dev} irq:${irq} msi_irqs:${msi_irqs}) with cpus (${cpulist})"
|
||||
|
||||
for i in $(echo "${irq} ${msi_irqs}"); do echo $i; done | \
|
||||
xargs --no-run-if-empty -i{} \
|
||||
/bin/bash -c "[[ -e /proc/irq/{} ]] && echo ${cpulist} > /proc/irq/{}/smp_affinity_list" 2>/dev/null
|
||||
|
||||
exit 0
|
||||
163
utilities/worker-utils/worker-utils/affine-platform.sh
Executable file
163
utilities/worker-utils/worker-utils/affine-platform.sh
Executable file
@@ -0,0 +1,163 @@
|
||||
#!/bin/bash
|
||||
################################################################################
|
||||
# Copyright (c) 2013 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
################################################################################
|
||||
# Define minimal path
|
||||
PATH=/bin:/usr/bin:/usr/local/bin
|
||||
|
||||
LOG_FUNCTIONS=${LOG_FUNCTIONS:-"/etc/init.d/log_functions.sh"}
|
||||
CPUMAP_FUNCTIONS=${CPUMAP_FUNCTIONS:-"/etc/init.d/cpumap_functions.sh"}
|
||||
TASK_AFFINITY_FUNCTIONS=${TASK_AFFINITY_FUNCTIONS:-"/etc/init.d/task_affinity_functions.sh"}
|
||||
source /etc/init.d/functions
|
||||
[[ -e ${LOG_FUNCTIONS} ]] && source ${LOG_FUNCTIONS}
|
||||
[[ -e ${CPUMAP_FUNCTIONS} ]] && source ${CPUMAP_FUNCTIONS}
|
||||
[[ -e ${TASK_AFFINITY_FUNCTIONS} ]] && source ${TASK_AFFINITY_FUNCTIONS}
|
||||
linkname=$(readlink -n -f $0)
|
||||
scriptname=$(basename $linkname)
|
||||
|
||||
# Enable debug logs
|
||||
LOG_DEBUG=1
|
||||
|
||||
. /etc/platform/platform.conf
|
||||
|
||||
################################################################################
|
||||
# Affine all running tasks to the CPULIST provided in the first parameter.
|
||||
################################################################################
|
||||
function affine_tasks {
|
||||
local CPULIST=$1
|
||||
local PIDLIST
|
||||
local RET=0
|
||||
|
||||
# Affine non-kernel-thread tasks (excluded [kthreadd] and its children) to all available
|
||||
# cores. They will be reaffined to platform cores later on as part of nova-compute
|
||||
# launch.
|
||||
log_debug "Affining all tasks to all available CPUs..."
|
||||
affine_tasks_to_all_cores
|
||||
RET=$?
|
||||
if [ $RET -ne 0 ]; then
|
||||
log_error "Some tasks failed to be affined to all cores."
|
||||
fi
|
||||
|
||||
# Get number of logical cpus
|
||||
N_CPUS=$(cat /proc/cpuinfo 2>/dev/null | \
|
||||
awk '/^[pP]rocessor/ { n +=1 } END { print (n>0) ? n : 1}')
|
||||
|
||||
# Calculate platform cores cpumap
|
||||
PLATFORM_COREMASK=$(cpulist_to_cpumap ${CPULIST} ${N_CPUS})
|
||||
|
||||
# Set default IRQ affinity
|
||||
echo ${PLATFORM_COREMASK} > /proc/irq/default_smp_affinity
|
||||
|
||||
# Affine all PCI/MSI interrupts to platform cores; this overrides
|
||||
# irqaffinity boot arg, since that does not handle IRQs for PCI devices
|
||||
# on numa nodes that do not intersect with platform cores.
|
||||
PCIDEVS=/sys/bus/pci/devices
|
||||
declare -a irqs=()
|
||||
irqs+=($(cat ${PCIDEVS}/*/irq 2>/dev/null | xargs))
|
||||
irqs+=($(ls ${PCIDEVS}/*/msi_irqs 2>/dev/null | grep -E '^[0-9]+$' | xargs))
|
||||
# flatten list of irqs, removing duplicates
|
||||
irqs=($(echo ${irqs[@]} | tr ' ' '\n' | sort -nu))
|
||||
log_debug "Affining all PCI/MSI irqs(${irqs[@]}) with cpus (${CPULIST})"
|
||||
for i in ${irqs[@]}; do
|
||||
/bin/bash -c "[[ -e /proc/irq/${i} ]] && echo ${CPULIST} > /proc/irq/${i}/smp_affinity_list" 2>/dev/null
|
||||
done
|
||||
if [[ "$subfunction" == *"worker,lowlatency" ]]; then
|
||||
# Affine work queues to platform cores
|
||||
echo ${PLATFORM_COREMASK} > /sys/devices/virtual/workqueue/cpumask
|
||||
echo ${PLATFORM_COREMASK} > /sys/bus/workqueue/devices/writeback/cpumask
|
||||
|
||||
# On low latency compute reassign the per cpu threads rcuc, ksoftirq,
|
||||
# ktimersoftd to FIFO along with the specified priority
|
||||
PIDLIST=$( ps -e -p 2 |grep rcuc | awk '{ print $1; }')
|
||||
for PID in ${PIDLIST[@]}; do
|
||||
chrt -p -f 4 ${PID} 2>/dev/null
|
||||
done
|
||||
|
||||
PIDLIST=$( ps -e -p 2 |grep ksoftirq | awk '{ print $1; }')
|
||||
for PID in ${PIDLIST[@]}; do
|
||||
chrt -p -f 2 ${PID} 2>/dev/null
|
||||
done
|
||||
|
||||
PIDLIST=$( ps -e -p 2 |grep ktimersoftd | awk '{ print $1; }')
|
||||
for PID in ${PIDLIST[@]}; do
|
||||
chrt -p -f 3 ${PID} 2>/dev/null
|
||||
done
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# Start Action
|
||||
################################################################################
|
||||
function start {
|
||||
local RET=0
|
||||
|
||||
echo -n "Starting ${scriptname}: "
|
||||
|
||||
## Check whether we are root (need root for taskset)
|
||||
if [ $UID -ne 0 ]; then
|
||||
log_error "require root or sudo"
|
||||
RET=1
|
||||
return ${RET}
|
||||
fi
|
||||
|
||||
## Define platform cpulist to be thread siblings of core 0
|
||||
PLATFORM_CPULIST=$(get_platform_cpu_list)
|
||||
|
||||
# Affine all tasks to platform cpulist
|
||||
affine_tasks ${PLATFORM_CPULIST}
|
||||
RET=$?
|
||||
if [ ${RET} -ne 0 ]; then
|
||||
log_error "Failed to affine tasks ${PLATFORM_CPULIST}, rc=${RET}"
|
||||
return ${RET}
|
||||
fi
|
||||
|
||||
print_status ${RET}
|
||||
return ${RET}
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# Stop Action - don't do anything
|
||||
################################################################################
|
||||
function stop {
|
||||
local RET=0
|
||||
echo -n "Stopping ${scriptname}: "
|
||||
print_status ${RET}
|
||||
return ${RET}
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# Restart Action
|
||||
################################################################################
|
||||
function restart {
|
||||
stop
|
||||
start
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# Main Entry
|
||||
#
|
||||
################################################################################
|
||||
case "$1" in
|
||||
start)
|
||||
start
|
||||
;;
|
||||
stop)
|
||||
stop
|
||||
;;
|
||||
restart|reload)
|
||||
restart
|
||||
;;
|
||||
status)
|
||||
echo -n "OK"
|
||||
;;
|
||||
*)
|
||||
echo $"Usage: $0 {start|stop|restart|reload|status}"
|
||||
exit 1
|
||||
esac
|
||||
|
||||
exit $?
|
||||
@@ -0,0 +1,14 @@
|
||||
[Unit]
|
||||
Description=Titanium Cloud Affine Platform
|
||||
After=syslog.service network.service dbus.service sw-patch.service
|
||||
Before=workerconfig.service
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
RemainAfterExit=yes
|
||||
ExecStart=/etc/init.d/affine-platform.sh start
|
||||
ExecStop=/etc/init.d/affine-platform.sh stop
|
||||
ExecReload=/etc/init.d/affine-platform.sh restart
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
383
utilities/worker-utils/worker-utils/cpumap_functions.sh
Normal file
383
utilities/worker-utils/worker-utils/cpumap_functions.sh
Normal file
@@ -0,0 +1,383 @@
|
||||
#!/bin/bash
|
||||
################################################################################
|
||||
# Copyright (c) 2013-2018 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
################################################################################
|
||||
|
||||
source /etc/platform/platform.conf
|
||||
|
||||
################################################################################
|
||||
# Utility function to expand a sequence of numbers (e.g., 0-7,16-23)
|
||||
################################################################################
|
||||
function expand_sequence {
|
||||
SEQUENCE=(${1//,/ })
|
||||
DELIMITER=${2:-","}
|
||||
|
||||
LIST=
|
||||
for entry in ${SEQUENCE[@]}; do
|
||||
range=(${entry/-/ })
|
||||
a=${range[0]}
|
||||
b=${range[1]:-${range[0]}}
|
||||
|
||||
for i in $(seq $a $b); do
|
||||
LIST="${LIST}${DELIMITER}${i}"
|
||||
done
|
||||
done
|
||||
echo ${LIST:1}
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# Append a string to comma separated list string
|
||||
################################################################################
|
||||
function append_list {
|
||||
local PUSH=$1
|
||||
local LIST=$2
|
||||
if [ -z "${LIST}" ]; then
|
||||
LIST=${PUSH}
|
||||
else
|
||||
LIST="${LIST},${PUSH}"
|
||||
fi
|
||||
echo ${LIST}
|
||||
return 0
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# Condense a sequence of numbers to a list of ranges (e.g, 7-12,15-16)
|
||||
################################################################################
|
||||
function condense_sequence {
|
||||
local arr=( $(printf '%s\n' "$@" | sort -n) )
|
||||
local first
|
||||
local last
|
||||
local cpulist=""
|
||||
for ((i=0; i < ${#arr[@]}; i++)); do
|
||||
num=${arr[$i]}
|
||||
if [[ -z $first ]]; then
|
||||
first=$num
|
||||
last=$num
|
||||
continue
|
||||
fi
|
||||
if [[ num -ne $((last + 1)) ]]; then
|
||||
if [[ first -eq last ]]; then
|
||||
cpulist=$(append_list ${first} ${cpulist})
|
||||
else
|
||||
cpulist=$(append_list "${first}-${last}" ${cpulist})
|
||||
fi
|
||||
first=$num
|
||||
last=$num
|
||||
else
|
||||
: $((last++))
|
||||
fi
|
||||
done
|
||||
if [[ first -eq last ]]; then
|
||||
cpulist=$(append_list ${first} ${cpulist})
|
||||
else
|
||||
cpulist=$(append_list "${first}-${last}" ${cpulist})
|
||||
fi
|
||||
echo "$cpulist"
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# Converts a CPULIST (e.g., 0-7,16-23) to a CPUMAP (e.g., 0x00FF00FF). The
|
||||
# CPU map is returned as a string representation of a large hexidecimal
|
||||
# number but without the leading "0x" characters.
|
||||
#
|
||||
################################################################################
|
||||
function cpulist_to_cpumap {
|
||||
local CPULIST=$1
|
||||
local NR_CPUS=$2
|
||||
local CPUMAP=0
|
||||
local CPUID=0
|
||||
if [ -z "${NR_CPUS}" ] || [ ${NR_CPUS} -eq 0 ]; then
|
||||
echo 0
|
||||
return 0
|
||||
fi
|
||||
for CPUID in $(expand_sequence $CPULIST " "); do
|
||||
if [ "${CPUID}" -lt "${NR_CPUS}" ]; then
|
||||
CPUMAP=$(echo "${CPUMAP} + (2^${CPUID})" | bc -l)
|
||||
fi
|
||||
done
|
||||
|
||||
echo "obase=16;ibase=10;${CPUMAP}" | bc -l
|
||||
return 0
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# Converts a CPUMAP (e.g., 0x00FF00FF) to a CPULIST (e.g., 0-7,16-23). The
|
||||
# CPUMAP is expected in hexidecimal (base=10) form without the leading "0x"
|
||||
# characters.
|
||||
#
|
||||
################################################################################
|
||||
function cpumap_to_cpulist {
|
||||
local CPUMAP
|
||||
CPUMAP=$(echo "obase=10;ibase=16;$1" | bc -l)
|
||||
local NR_CPUS=$2
|
||||
local list=()
|
||||
local cpulist=""
|
||||
for((i=0; i < NR_CPUS; i++))
|
||||
do
|
||||
## Since 'bc' does not support any bitwise operators this expression:
|
||||
## if (CPUMAP & (1 << CPUID))
|
||||
## has to be rewritten like this:
|
||||
## if (CPUMAP % (2**(CPUID+1)) > ((2**(CPUID)) - 1))
|
||||
##
|
||||
ISSET=$(echo "scale=0; (${CPUMAP} % 2^(${i}+1)) > (2^${i})-1" | bc -l)
|
||||
if [ "${ISSET}" -ne 0 ]; then
|
||||
list+=($i)
|
||||
fi
|
||||
done
|
||||
cpulist=$(condense_sequence ${list[@]} )
|
||||
echo "$cpulist"
|
||||
return 0
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# Bitwise NOT of a hexidecimal representation of a CPULIST. The value is
|
||||
# returned as a hexidecimal value but without the leading "0x" characters
|
||||
#
|
||||
################################################################################
|
||||
function invert_cpumap {
|
||||
local CPUMAP
|
||||
CPUMAP=$(echo "obase=10;ibase=16;$1" | bc -l)
|
||||
local NR_CPUS=$2
|
||||
local INVERSE_CPUMAP=0
|
||||
|
||||
for CPUID in $(seq 0 $((NR_CPUS - 1))); do
|
||||
## See comment in previous function
|
||||
ISSET=$(echo "scale=0; (${CPUMAP} % 2^(${CPUID}+1)) > (2^${CPUID})-1" | bc -l)
|
||||
if [ "${ISSET}" -eq 1 ]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
INVERSE_CPUMAP=$(echo "${INVERSE_CPUMAP} + (2^${CPUID})" | bc -l)
|
||||
done
|
||||
|
||||
echo "obase=16;ibase=10;${INVERSE_CPUMAP}" | bc -l
|
||||
return 0
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# Builds the complement representation of a CPULIST
|
||||
#
|
||||
################################################################################
|
||||
function invert_cpulist {
|
||||
local CPULIST=$1
|
||||
local NR_CPUS=$2
|
||||
local CPUMAP
|
||||
CPUMAP=$(cpulist_to_cpumap ${CPULIST} ${NR_CPUS})
|
||||
cpumap_to_cpulist $(invert_cpumap ${CPUMAP} ${NR_CPUS}) ${NR_CPUS}
|
||||
return 0
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# in_list() - check whether item is contained in list
|
||||
# param: item
|
||||
# param: list (i.e. 0-3,8-11)
|
||||
# returns: 0 - item is contained in list;
|
||||
# 1 - item is not contained in list
|
||||
#
|
||||
################################################################################
|
||||
function in_list {
|
||||
local item="$1"
|
||||
local list="$2"
|
||||
|
||||
# expand list format 0-3,8-11 to a full sequence {0..3} {8..11}
|
||||
local exp_list
|
||||
exp_list=$(echo ${list} | \
|
||||
sed -e 's#,# #g' -e 's#\([0-9]*\)-\([0-9]*\)#{\1\.\.\2}#g')
|
||||
|
||||
local e
|
||||
for e in $(eval echo ${exp_list}); do
|
||||
[[ "$e" == "$item" ]] && return 0
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# any_in_list() - check if any item of sublist is contained in list
|
||||
# param: sublist
|
||||
# param: list
|
||||
# returns: 0 - an item of sublist is contained in list;
|
||||
# 1 - no sublist items contained in list
|
||||
#
|
||||
################################################################################
|
||||
function any_in_list {
|
||||
local sublist="$1"
|
||||
local list="$2"
|
||||
local e
|
||||
local exp_list
|
||||
|
||||
# expand list format 0-3,8-11 to a full sequence {0..3} {8..11}
|
||||
exp_list=$(echo ${list} | \
|
||||
sed -e 's#,# #g' -e 's#\([0-9]*\)-\([0-9]*\)#{\1\.\.\2}#g')
|
||||
declare -A a_list
|
||||
for e in $(eval echo ${exp_list}); do
|
||||
a_list[$e]=1
|
||||
done
|
||||
|
||||
# expand list format 0-3,8-11 to a full sequence {0..3} {8..11}
|
||||
exp_list=$(echo ${sublist} | \
|
||||
sed -e 's#,# #g' -e 's#\([0-9]*\)-\([0-9]*\)#{\1\.\.\2}#g')
|
||||
declare -A a_sublist
|
||||
for e in $(eval echo ${exp_list}); do
|
||||
a_sublist[$e]=1
|
||||
done
|
||||
|
||||
# Check if any element of sublist is in list
|
||||
for e in "${!a_sublist[@]}"; do
|
||||
if [[ "${a_list[$e]}" == 1 ]]; then
|
||||
return 0 # matches
|
||||
fi
|
||||
done
|
||||
return 1 # no match
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# Return list of CPUs reserved for platform
|
||||
################################################################################
|
||||
function get_platform_cpu_list {
|
||||
## Define platform cpulist based on engineering a number of cores and
|
||||
## whether this is a combo or not, and include SMT siblings.
|
||||
if [[ $subfunction = *worker* ]]; then
|
||||
RESERVE_CONF="/etc/platform/worker_reserved.conf"
|
||||
[[ -e ${RESERVE_CONF} ]] && source ${RESERVE_CONF}
|
||||
if [ -n "$PLATFORM_CPU_LIST" ];then
|
||||
echo "$PLATFORM_CPU_LIST"
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
|
||||
local PLATFORM_SOCKET=0
|
||||
local PLATFORM_START=0
|
||||
local PLATFORM_CORES=1
|
||||
if [ "$nodetype" = "controller" ]; then
|
||||
PLATFORM_CORES=$(($PLATFORM_CORES+1))
|
||||
fi
|
||||
local PLATFORM_CPULIST
|
||||
PLATFORM_CPULIST=$(topology_to_cpulist ${PLATFORM_SOCKET} ${PLATFORM_START} ${PLATFORM_CORES})
|
||||
echo ${PLATFORM_CPULIST}
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# Return list of CPUs reserved for vswitch
|
||||
################################################################################
|
||||
function get_vswitch_cpu_list {
|
||||
## Define default avp cpulist based on engineered number of platform cores,
|
||||
## engineered avp cores, and include SMT siblings.
|
||||
if [[ $subfunction = *worker* ]]; then
|
||||
VSWITCH_CONF="/etc/vswitch/vswitch.conf"
|
||||
[[ -e ${VSWITCH_CONF} ]] && source ${VSWITCH_CONF}
|
||||
if [ -n "$VSWITCH_CPU_LIST" ];then
|
||||
echo "$VSWITCH_CPU_LIST"
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
|
||||
local N_CORES_IN_PKG
|
||||
N_CORES_IN_PKG=$(cat /proc/cpuinfo 2>/dev/null | \
|
||||
awk '/^cpu cores/ {n = $4} END { print (n>0) ? n : 1 }')
|
||||
# engineer platform cores
|
||||
local PLATFORM_CORES=1
|
||||
if [ "$nodetype" = "controller" ]; then
|
||||
PLATFORM_CORES=$(($PLATFORM_CORES+1))
|
||||
fi
|
||||
|
||||
# engineer AVP cores
|
||||
local AVP_SOCKET=0
|
||||
local AVP_START=${PLATFORM_CORES}
|
||||
local AVP_CORES=1
|
||||
if [ ${N_CORES_IN_PKG} -gt 4 ]; then
|
||||
AVP_CORES=$(($AVP_CORES+1))
|
||||
fi
|
||||
local AVP_CPULIST
|
||||
AVP_CPULIST=$(topology_to_cpulist ${AVP_SOCKET} ${AVP_START} ${AVP_CORES})
|
||||
echo ${AVP_CPULIST}
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# vswitch_expanded_cpu_list() - compute the vswitch cpu list, including it's siblings
|
||||
################################################################################
|
||||
function vswitch_expanded_cpu_list {
|
||||
list=$(get_vswitch_cpu_list)
|
||||
|
||||
# Expand vswitch cpulist
|
||||
vswitch_cpulist=$(expand_sequence ${list} " ")
|
||||
|
||||
cpulist=""
|
||||
for e in $vswitch_cpulist; do
|
||||
# claim hyperthread siblings if SMT enabled
|
||||
SIBLINGS_CPULIST=$(cat /sys/devices/system/cpu/cpu${e}/topology/thread_siblings_list 2>/dev/null)
|
||||
siblings_cpulist=$(expand_sequence ${SIBLINGS_CPULIST} " ")
|
||||
for s in $siblings_cpulist; do
|
||||
in_list ${s} ${cpulist}
|
||||
if [ $? -eq 1 ]; then
|
||||
cpulist=$(append_list ${s} ${cpulist})
|
||||
fi
|
||||
done
|
||||
done
|
||||
|
||||
echo "$cpulist"
|
||||
return 0
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# platform_expanded_cpu_list() - compute the platform cpu list, including it's siblings
|
||||
################################################################################
|
||||
function platform_expanded_cpu_list {
|
||||
list=$(get_platform_cpu_list)
|
||||
|
||||
# Expand platform cpulist
|
||||
platform_cpulist=$(expand_sequence ${list} " ")
|
||||
|
||||
cpulist=""
|
||||
for e in $platform_cpulist; do
|
||||
# claim hyperthread siblings if SMT enabled
|
||||
SIBLINGS_CPULIST=$(cat /sys/devices/system/cpu/cpu${e}/topology/thread_siblings_list 2>/dev/null)
|
||||
siblings_cpulist=$(expand_sequence ${SIBLINGS_CPULIST} " ")
|
||||
for s in $siblings_cpulist; do
|
||||
in_list ${s} ${cpulist}
|
||||
if [ $? -eq 1 ]; then
|
||||
cpulist=$(append_list ${s} ${cpulist})
|
||||
fi
|
||||
done
|
||||
done
|
||||
|
||||
echo "$cpulist"
|
||||
return 0
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# Return list of CPUs based on cpu topology. Select the socket, starting core
|
||||
# within the socket, select number of cores, and SMT siblings.
|
||||
################################################################################
|
||||
function topology_to_cpulist {
|
||||
local SOCKET=$1
|
||||
local CORE_START=$2
|
||||
local NUM_CORES=$3
|
||||
local CPULIST
|
||||
CPULIST=$(cat /proc/cpuinfo 2>/dev/null | perl -sne \
|
||||
'BEGIN { %T = {}; %H = {}; $L = $P = $C = $S = 0; }
|
||||
{
|
||||
if (/processor\s+:\s+(\d+)/) { $L = $1; }
|
||||
if (/physical id\s+:\s+(\d+)/) { $P = $1; }
|
||||
if (/core id\s+:\s+(\d+)/) {
|
||||
$C = $1;
|
||||
$T{$P}{$C}++;
|
||||
$S = $T{$P}{$C};
|
||||
$H{$P}{$C}{$S} = $L;
|
||||
}
|
||||
}
|
||||
END {
|
||||
@cores = sort { $a <=> $b } keys $T{$socket};
|
||||
@sel_cores = splice @cores, $core_start, $num_cores;
|
||||
@lcpus = ();
|
||||
for $C (@sel_cores) {
|
||||
for $S (sort {$a <=> $b } keys %{ $H{$socket}{$C} }) {
|
||||
push @lcpus, $H{$socket}{$C}{$S};
|
||||
}
|
||||
}
|
||||
printf "%s\n", join(",", @lcpus);
|
||||
}' -- -socket=${SOCKET} -core_start=${CORE_START} -num_cores=${NUM_CORES})
|
||||
echo ${CPULIST}
|
||||
}
|
||||
@@ -0,0 +1,241 @@
|
||||
#!/bin/bash
|
||||
|
||||
#
|
||||
# Copyright (c) 2015-2016 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
source /etc/init.d/cpumap_functions.sh
|
||||
|
||||
export NR_CPUS_LIST=("4" "8" "16" "32" "64" "128")
|
||||
if [ ! -z ${1} ]; then
|
||||
NR_CPUS_LIST=(${1//,/ })
|
||||
fi
|
||||
|
||||
function test_cpumap_to_cpulist {
|
||||
local NR_CPUS=$1
|
||||
declare -A CPULISTS
|
||||
|
||||
if [ ${NR_CPUS} -ge 4 ]; then
|
||||
CPULISTS["0"]=""
|
||||
CPULISTS["1"]="0"
|
||||
CPULISTS["2"]="1"
|
||||
CPULISTS["3"]="0-1"
|
||||
CPULISTS["5"]="0,2"
|
||||
CPULISTS["7"]="0-2"
|
||||
CPULISTS["F"]="0-3"
|
||||
CPULISTS["9"]="0,3"
|
||||
fi
|
||||
if [ ${NR_CPUS} -ge 8 ]; then
|
||||
CPULISTS["00"]=""
|
||||
CPULISTS["11"]="0,4"
|
||||
CPULISTS["FF"]="0-7"
|
||||
CPULISTS["81"]="0,7"
|
||||
fi
|
||||
if [ ${NR_CPUS} -ge 16 ]; then
|
||||
CPULISTS["0000"]=""
|
||||
CPULISTS["1111"]="0,4,8,12"
|
||||
CPULISTS["FFF"]="0-11"
|
||||
CPULISTS["F0F"]="0-3,8-11"
|
||||
CPULISTS["F0F0"]="4-7,12-15"
|
||||
CPULISTS["FFFF"]="0-15"
|
||||
CPULISTS["FFFE"]="1-15"
|
||||
CPULISTS["8001"]="0,15"
|
||||
fi
|
||||
if [ ${NR_CPUS} -ge 32 ]; then
|
||||
CPULISTS["00000000"]=""
|
||||
CPULISTS["11111111"]="0,4,8,12,16,20,24,28"
|
||||
CPULISTS["0F0F0F0F"]="0-3,8-11,16-19,24-27"
|
||||
CPULISTS["F0F0F0F0"]="4-7,12-15,20-23,28-31"
|
||||
CPULISTS["FFFFFFFF"]="0-31"
|
||||
CPULISTS["FFFFFFFE"]="1-31"
|
||||
CPULISTS["80000001"]="0,31"
|
||||
fi
|
||||
if [ ${NR_CPUS} -ge 64 ]; then
|
||||
CPULISTS["0000000000000000"]=""
|
||||
CPULISTS["1111111111111111"]="0,4,8,12,16,20,24,28,32,36,40,44,48,52,56,60"
|
||||
CPULISTS["0F0F0F0F0F0F0F0F"]="0-3,8-11,16-19,24-27,32-35,40-43,48-51,56-59"
|
||||
CPULISTS["F0F0F0F0F0F0F0F0"]="4-7,12-15,20-23,28-31,36-39,44-47,52-55,60-63"
|
||||
CPULISTS["FFFFFFFFFFFFFFFF"]="0-63"
|
||||
CPULISTS["FFFFFFFFFFFFFFFE"]="1-63"
|
||||
CPULISTS["8000000000000001"]="0,63"
|
||||
fi
|
||||
if [ ${NR_CPUS} -ge 128 ]; then
|
||||
CPULISTS["00000000000000000000000000000000"]=""
|
||||
CPULISTS["11111111111111111111111111111111"]="0,4,8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76,80,84,88,92,96,100,104,108,112,116,120,124"
|
||||
CPULISTS["0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F"]="0-3,8-11,16-19,24-27,32-35,40-43,48-51,56-59,64-67,72-75,80-83,88-91,96-99,104-107,112-115,120-123"
|
||||
CPULISTS["F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0"]="4-7,12-15,20-23,28-31,36-39,44-47,52-55,60-63,68-71,76-79,84-87,92-95,100-103,108-111,116-119,124-127"
|
||||
CPULISTS["FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"]="0-127"
|
||||
CPULISTS["FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE"]="1-127"
|
||||
CPULISTS["80000000000000000000000000000001"]="0,127"
|
||||
fi
|
||||
|
||||
for CPUMAP in ${!CPULISTS[@]}; do
|
||||
EXPECTED=${CPULISTS[${CPUMAP}]}
|
||||
CPULIST=$(cpumap_to_cpulist ${CPUMAP} ${NR_CPUS})
|
||||
if [ "${CPULIST}" != "${EXPECTED}" ]; then
|
||||
printf "\n"
|
||||
echo "error: (cpumap_to_list ${CPUMAP} ${NR_CPUS}) returned \"${CPULIST}\" instead of \"${EXPECTED}\""
|
||||
fi
|
||||
printf "."
|
||||
done
|
||||
|
||||
printf "\n"
|
||||
}
|
||||
|
||||
function test_cpulist_to_cpumap {
|
||||
local NR_CPUS=$1
|
||||
declare -A CPUMAPS
|
||||
|
||||
if [ ${NR_CPUS} -ge 4 ]; then
|
||||
CPUMAPS[" "]="0"
|
||||
CPUMAPS["0"]="1"
|
||||
CPUMAPS["1"]="2"
|
||||
CPUMAPS["0-1"]="3"
|
||||
CPUMAPS["0,2"]="5"
|
||||
CPUMAPS["0-2"]="7"
|
||||
CPUMAPS["0-3"]="F"
|
||||
CPUMAPS["0,3"]="9"
|
||||
fi
|
||||
if [ ${NR_CPUS} -ge 8 ]; then
|
||||
CPUMAPS["0,4"]="11"
|
||||
CPUMAPS["0-7"]="FF"
|
||||
CPUMAPS["0,7"]="81"
|
||||
fi
|
||||
if [ ${NR_CPUS} -ge 16 ]; then
|
||||
CPUMAPS["0,4,8,12"]="1111"
|
||||
CPUMAPS["0-11"]="FFF"
|
||||
CPUMAPS["0-3,8-11"]="F0F"
|
||||
CPUMAPS["4-7,12-15"]="F0F0"
|
||||
CPUMAPS["0-15"]="FFFF"
|
||||
CPUMAPS["1-15"]="FFFE"
|
||||
CPUMAPS["0,15"]="8001"
|
||||
fi
|
||||
if [ ${NR_CPUS} -ge 32 ]; then
|
||||
CPUMAPS["0,4,8,12,16,20,24,28"]="11111111"
|
||||
CPUMAPS["0-3,8-11,16-19,24-27"]="F0F0F0F"
|
||||
CPUMAPS["4-7,12-15,20-23,28-31"]="F0F0F0F0"
|
||||
CPUMAPS["0-31"]="FFFFFFFF"
|
||||
CPUMAPS["1-31"]="FFFFFFFE"
|
||||
CPUMAPS["0,31"]="80000001"
|
||||
fi
|
||||
if [ ${NR_CPUS} -ge 64 ]; then
|
||||
CPUMAPS["0,4,8,12,16,20,24,28,32,36,40,44,48,52,56,60"]="1111111111111111"
|
||||
CPUMAPS["0-3,8-11,16-19,24-27,32-35,40-43,48-51,56-59"]="F0F0F0F0F0F0F0F"
|
||||
CPUMAPS["4-7,12-15,20-23,28-31,36-39,44-47,52-55,60-63"]="F0F0F0F0F0F0F0F0"
|
||||
CPUMAPS["0-63"]="FFFFFFFFFFFFFFFF"
|
||||
CPUMAPS["1-63"]="FFFFFFFFFFFFFFFE"
|
||||
CPUMAPS["0,63"]="8000000000000001"
|
||||
fi
|
||||
if [ ${NR_CPUS} -ge 128 ]; then
|
||||
CPUMAPS["0,4,8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76,80,84,88,92,96,100,104,108,112,116,120,124"]="11111111111111111111111111111111"
|
||||
CPUMAPS["0-3,8-11,16-19,24-27,32-35,40-43,48-51,56-59,64-67,72-75,80-83,88-91,96-99,104-107,112-115,120-123"]="F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F"
|
||||
CPUMAPS["4-7,12-15,20-23,28-31,36-39,44-47,52-55,60-63,68-71,76-79,84-87,92-95,100-103,108-111,116-119,124-127"]="F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0"
|
||||
CPUMAPS["0-127"]="FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
|
||||
CPUMAPS["1-127"]="FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE"
|
||||
CPUMAPS["0,127"]="80000000000000000000000000000001"
|
||||
fi
|
||||
|
||||
for CPULIST in ${!CPUMAPS[@]}; do
|
||||
EXPECTED=${CPUMAPS[${CPULIST}]}
|
||||
CPUMAP=$(cpulist_to_cpumap ${CPULIST} ${NR_CPUS})
|
||||
if [ "${CPUMAP}" != "${EXPECTED}" ]; then
|
||||
printf "\n"
|
||||
echo "error: (cpulist_to_cpumap ${CPULIST} ${NR_CPUS}) returned \"${CPUMAP}\" instead of \"${EXPECTED}\""
|
||||
fi
|
||||
printf "."
|
||||
done
|
||||
|
||||
printf "\n"
|
||||
}
|
||||
|
||||
function test_invert_cpumap {
|
||||
local NR_CPUS=$1
|
||||
declare -A INVERSES
|
||||
|
||||
if [ $((${NR_CPUS} % 4)) -ne 0 ]; then
|
||||
echo "test_invert_cpumap skipping NR_CPUS=${NR_CPUS}; not a multiple of 4"
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [ ${NR_CPUS} -ge 4 ]; then
|
||||
INVERSES["0"]="FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
|
||||
INVERSES["1"]="FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE"
|
||||
INVERSES["2"]="FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD"
|
||||
INVERSES["3"]="FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC"
|
||||
INVERSES["5"]="FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA"
|
||||
INVERSES["7"]="FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8"
|
||||
INVERSES["F"]="FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0"
|
||||
INVERSES["9"]="FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6"
|
||||
fi
|
||||
if [ ${NR_CPUS} -ge 8 ]; then
|
||||
INVERSES["11"]="FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEE"
|
||||
INVERSES["FF"]="FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00"
|
||||
INVERSES["F0"]="FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0F"
|
||||
INVERSES["81"]="FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7E"
|
||||
fi
|
||||
if [ ${NR_CPUS} -ge 16 ]; then
|
||||
INVERSES["1111"]="FFFFFFFFFFFFFFFFFFFFFFFFFFFFEEEE"
|
||||
INVERSES["FFF"]="FFFFFFFFFFFFFFFFFFFFFFFFFFFFF000"
|
||||
INVERSES["F0F"]="FFFFFFFFFFFFFFFFFFFFFFFFFFFFF0F0"
|
||||
INVERSES["F0F0"]="FFFFFFFFFFFFFFFFFFFFFFFFFFFF0F0F"
|
||||
INVERSES["0F0F"]="FFFFFFFFFFFFFFFFFFFFFFFFFFFFF0F0"
|
||||
INVERSES["FFFF"]="FFFFFFFFFFFFFFFFFFFFFFFFFFFF0000"
|
||||
INVERSES["FFFE"]="FFFFFFFFFFFFFFFFFFFFFFFFFFFF0001"
|
||||
INVERSES["8001"]="FFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFE"
|
||||
fi
|
||||
if [ ${NR_CPUS} -ge 32 ]; then
|
||||
INVERSES["11111111"]="FFFFFFFFFFFFFFFFFFFFFFFFEEEEEEEE"
|
||||
INVERSES["0F0F0F0F"]="FFFFFFFFFFFFFFFFFFFFFFFFF0F0F0F0"
|
||||
INVERSES["F0F0F0F0"]="FFFFFFFFFFFFFFFFFFFFFFFF0F0F0F0F"
|
||||
INVERSES["FFFFFFFF"]="FFFFFFFFFFFFFFFFFFFFFFFF00000000"
|
||||
INVERSES["FFFFFFFE"]="FFFFFFFFFFFFFFFFFFFFFFFF00000001"
|
||||
INVERSES["80000001"]="FFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFE"
|
||||
fi
|
||||
if [ ${NR_CPUS} -ge 64 ]; then
|
||||
INVERSES["1111111111111111"]="FFFFFFFFFFFFFFFFEEEEEEEEEEEEEEEE"
|
||||
INVERSES["0F0F0F0F0F0F0F0F"]="FFFFFFFFFFFFFFFFF0F0F0F0F0F0F0F0"
|
||||
INVERSES["F0F0F0F0F0F0F0F0"]="FFFFFFFFFFFFFFFF0F0F0F0F0F0F0F0F"
|
||||
INVERSES["FFFFFFFFFFFFFFFF"]="FFFFFFFFFFFFFFFF0000000000000000"
|
||||
INVERSES["FFFFFFFFFFFFFFFE"]="FFFFFFFFFFFFFFFF0000000000000001"
|
||||
INVERSES["8000000000000001"]="FFFFFFFFFFFFFFFF7FFFFFFFFFFFFFFE"
|
||||
fi
|
||||
if [ ${NR_CPUS} -ge 128 ]; then
|
||||
INVERSES["11111111111111111111111111111111"]="EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE"
|
||||
INVERSES["0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F"]="F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0"
|
||||
INVERSES["F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0"]="0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F"
|
||||
INVERSES["FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"]="00000000000000000000000000000000"
|
||||
INVERSES["FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE"]="00000000000000000000000000000001"
|
||||
INVERSES["80000000000000000000000000000001"]="7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE"
|
||||
fi
|
||||
|
||||
for CPUMAP in ${!INVERSES[@]}; do
|
||||
EXPECTED=${INVERSES[${CPUMAP}]}
|
||||
if [ ${NR_CPUS} -lt 128 ]; then
|
||||
EXPECTED=$(echo ${EXPECTED} | cut --complement -c1-$((32-((${NR_CPUS}+3)/4))))
|
||||
fi
|
||||
EXPECTED=$(echo ${EXPECTED} | sed -e "s/^0*//")
|
||||
if [ -z ${EXPECTED} ]; then
|
||||
EXPECTED="0"
|
||||
fi
|
||||
INVERSE=$(invert_cpumap ${CPUMAP} ${NR_CPUS})
|
||||
if [ "${INVERSE}" != "${EXPECTED}" ]; then
|
||||
printf "\n"
|
||||
echo "error: (invert_cpumap ${CPUMAP} ${NR_CPUS}) returned \"${INVERSE}\" instead of \"${EXPECTED}\""
|
||||
fi
|
||||
printf "."
|
||||
done
|
||||
|
||||
printf "\n"
|
||||
}
|
||||
|
||||
for NR_CPUS in ${NR_CPUS_LIST[@]}; do
|
||||
echo "NR_CPUS=${NR_CPUS}"
|
||||
test_cpumap_to_cpulist ${NR_CPUS}
|
||||
test_cpulist_to_cpumap ${NR_CPUS}
|
||||
test_invert_cpumap ${NR_CPUS}
|
||||
echo ""
|
||||
done
|
||||
|
||||
exit 0
|
||||
26
utilities/worker-utils/worker-utils/ps-sched.sh
Executable file
26
utilities/worker-utils/worker-utils/ps-sched.sh
Executable file
@@ -0,0 +1,26 @@
|
||||
#!/bin/bash
|
||||
################################################################################
|
||||
# Copyright (c) 2013 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
################################################################################
|
||||
#
|
||||
# ps-sched.sh -- gives detailed task listing with scheduling attributes
|
||||
# -- this is cpu and scheduling intensive version (shell/taskset based)
|
||||
# (note: does not print fields 'group' or 'timeslice')
|
||||
|
||||
printf "%6s %6s %6s %1c %2s %4s %6s %4s %-24s %2s %-16s %s\n" "PID" "TID" "PPID" "S" "PO" "NICE" "RTPRIO" "PR" "AFFINITY" "P" "COMM" "COMMAND"
|
||||
ps -eL -o pid=,lwp=,ppid=,state=,class=,nice=,rtprio=,priority=,psr=,comm=,command= | \
|
||||
while read pid tid ppid state policy nice rtprio priority psr comm command; do
|
||||
bitmask=$(taskset -p $tid 2>/dev/null)
|
||||
aff=${bitmask##*: }
|
||||
if [ -z "${aff}" ]; then
|
||||
aff="0x0"
|
||||
else
|
||||
aff="0x${aff}"
|
||||
fi
|
||||
printf "%6d %6d %6d %1c %2s %4s %6s %4d %-24s %2d %-16s %s\n" $pid $tid $ppid $state $policy $nice $rtprio $priority $aff $psr $comm "$command"
|
||||
done
|
||||
|
||||
exit 0
|
||||
@@ -0,0 +1,89 @@
|
||||
#!/bin/bash
|
||||
|
||||
#
|
||||
# Copyright (c) 2017 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# Purpose: set PM QoS resume latency constraints for CPUs.
|
||||
# Usage: /usr/bin/set-cpu-wakeup-latency.sh policy cpulist
|
||||
# policy may be either "low" or "high" to set appropriate latency.
|
||||
# "low" means HALT (C1) is the deepest C-state we allow the CPU to enter.
|
||||
# "high" means we allow the CPU to sleep as deeply as possible.
|
||||
# cpulist is for specifying a numerical list of processors.
|
||||
# It may contain multiple items, separated by comma, and ranges.
|
||||
# For example, 0,5,7,9-11.
|
||||
|
||||
# Define minimal path
|
||||
PATH=/bin:/usr/bin:/usr/local/bin
|
||||
|
||||
LOG_FUNCTIONS=${LOG_FUNCTIONS:-"/etc/init.d/log_functions.sh"}
|
||||
CPUMAP_FUNCTIONS=${CPUMAP_FUNCTIONS:-"/etc/init.d/cpumap_functions.sh"}
|
||||
[[ -e ${LOG_FUNCTIONS} ]] && source ${LOG_FUNCTIONS}
|
||||
[[ -e ${CPUMAP_FUNCTIONS} ]] && source ${CPUMAP_FUNCTIONS}
|
||||
|
||||
if [ $UID -ne 0 ]; then
|
||||
log_error "$0 requires root or sudo privileges"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$#" -ne 2 ]; then
|
||||
log_error "$0 requires policy and cpulist parameters"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
POLICY=$1
|
||||
CPU_LIST=$2
|
||||
NUMBER_OF_CPUS=$(getconf _NPROCESSORS_CONF 2>/dev/null)
|
||||
STATUS=1
|
||||
|
||||
for CPU_NUM in $(expand_sequence "$CPU_LIST" " "); do
|
||||
# Check that we are not setting PM QoS policy for non-existing CPU
|
||||
if [ "$CPU_NUM" -lt "0" ] || [ "$CPU_NUM" -ge "$NUMBER_OF_CPUS" ]; then
|
||||
log_error "CPU number ${CPU_NUM} is invalid, available CPUs are 0-${NUMBER_OF_CPUS-1}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Obtain CPU wakeup latencies for all C-states available starting from operating state to deepest sleep
|
||||
declare -a LIMITS=()
|
||||
LIMITS+=($(cat /sys/devices/system/cpu/cpu${CPU_NUM}/cpuidle/state*/latency 2>/dev/null | xargs | sort))
|
||||
if [ ${#LIMITS[@]} -eq 0 ]; then
|
||||
log_debug "Failed to get PM QoS latency limits for CPU ${CPU_NUM}"
|
||||
fi
|
||||
|
||||
# Select appropriate CPU wakeup latency based on "low" or "high" policy
|
||||
case "${POLICY}" in
|
||||
"low")
|
||||
# Get first sleep state for "low" policy
|
||||
if [ ${#LIMITS[@]} -eq 0 ]; then
|
||||
LATENCY=1
|
||||
else
|
||||
LATENCY=${LIMITS[1]}
|
||||
fi
|
||||
;;
|
||||
"high")
|
||||
# Get deepest sleep state for "high" policy
|
||||
if [ ${#LIMITS[@]} -eq 0 ]; then
|
||||
LATENCY=1000
|
||||
else
|
||||
LATENCY=${LIMITS[${#LIMITS[@]}-1]}
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
log_error "Policy is invalid, can be either low or high"
|
||||
exit 1
|
||||
esac
|
||||
|
||||
# Set the latency for paricular CPU
|
||||
echo ${LATENCY} > /sys/devices/system/cpu/cpu${CPU_NUM}/power/pm_qos_resume_latency_us 2>/dev/null
|
||||
RET_VAL=$?
|
||||
if [ ${RET_VAL} -ne 0 ]; then
|
||||
log_error "Failed to set PM QoS latency for CPU ${CPU_NUM}, rc=${RET_VAL}"
|
||||
continue
|
||||
else
|
||||
log_debug "Succesfully set PM QoS latency for CPU ${CPU_NUM}, rc=${RET_VAL}"
|
||||
STATUS=0
|
||||
fi
|
||||
done
|
||||
|
||||
exit ${STATUS}
|
||||
322
utilities/worker-utils/worker-utils/task_affinity_functions.sh
Executable file
322
utilities/worker-utils/worker-utils/task_affinity_functions.sh
Executable file
@@ -0,0 +1,322 @@
|
||||
#!/bin/bash
|
||||
################################################################################
|
||||
# Copyright (c) 2017 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
################################################################################
|
||||
# Define minimal path
|
||||
PATH=/bin:/usr/bin:/usr/local/bin
|
||||
|
||||
. /etc/platform/platform.conf
|
||||
LOG_FUNCTIONS=${LOG_FUNCTIONS:-"/etc/init.d/log_functions.sh"}
|
||||
CPUMAP_FUNCTIONS=${CPUMAP_FUNCTIONS:-"/etc/init.d/cpumap_functions.sh"}
|
||||
[[ -e ${LOG_FUNCTIONS} ]] && source ${LOG_FUNCTIONS}
|
||||
[[ -e ${CPUMAP_FUNCTIONS} ]] && source ${CPUMAP_FUNCTIONS}
|
||||
|
||||
# Enable debug logs and tag them
|
||||
LOG_DEBUG=1
|
||||
TAG="TASKAFFINITY:"
|
||||
|
||||
TASK_AFFINING_INCOMPLETE="/etc/platform/.task_affining_incomplete"
|
||||
N_CPUS=$(cat /proc/cpuinfo 2>/dev/null | \
|
||||
awk '/^[pP]rocessor/ { n +=1 } END { print (n>0) ? n : 1}')
|
||||
FULLSET_CPUS="0-"$((N_CPUS-1))
|
||||
FULLSET_MASK=$(cpulist_to_cpumap ${FULLSET_CPUS} ${N_CPUS})
|
||||
PLATFORM_CPUS=$(get_platform_cpu_list)
|
||||
PLATFORM_CPULIST=$(get_platform_cpu_list| \
|
||||
perl -pe 's/(\d+)-(\d+)/join(",",$1..$2)/eg'| \
|
||||
sed 's/,/ /g')
|
||||
VSWITCH_CPULIST=$(get_vswitch_cpu_list| \
|
||||
perl -pe 's/(\d+)-(\d+)/join(",",$1..$2)/eg'| \
|
||||
sed 's/,/ /g')
|
||||
IDLE_MARK=95.0
|
||||
KERNEL=`uname -a`
|
||||
|
||||
################################################################################
|
||||
# Check if a given core is one of the platform cores
|
||||
################################################################################
|
||||
function is_platform_core {
|
||||
local core=$1
|
||||
for CPU in ${PLATFORM_CPULIST}; do
|
||||
if [ $core -eq $CPU ]; then
|
||||
return 1
|
||||
fi
|
||||
done
|
||||
return 0
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# Check if a given core is one of the vswitch cores
|
||||
################################################################################
|
||||
function is_vswitch_core {
|
||||
local core=$1
|
||||
for CPU in ${VSWITCH_CPULIST}; do
|
||||
if [ $core -eq $CPU ]; then
|
||||
return 1
|
||||
fi
|
||||
done
|
||||
return 0
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# An audit and corrective action following a swact
|
||||
################################################################################
|
||||
function audit_and_reaffine {
|
||||
local mask=$1
|
||||
local cmd_str=""
|
||||
local tasklist
|
||||
|
||||
cmd_str="ps-sched.sh|awk '(\$9==\"$mask\") {print \$2}'"
|
||||
|
||||
tasklist=($(eval $cmd_str))
|
||||
# log_debug "cmd str = $cmd_str"
|
||||
log_debug "${TAG} There are ${#tasklist[@]} tasks to reaffine."
|
||||
|
||||
for task in ${tasklist[@]}; do
|
||||
taskset -acp ${PLATFORM_CPUS} $task &> /dev/null
|
||||
rc=$?
|
||||
[[ $rc -ne 0 ]] && log_error "Failed to set CPU affinity for pid $pid, rc=$rc"
|
||||
done
|
||||
tasklist=($(eval $cmd_str))
|
||||
[[ ${#tasklist[@]} -eq 0 ]] && return 0 || return 1
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# The following function is used to verify that any sleeping management tasks
|
||||
# that are on non-platform cores can be migrated to platform cores as soon as
|
||||
# they are scheduled. It can be invoked either manually or from goenableCompute
|
||||
# script as a scheduled job (with a few minute delay) if desired.
|
||||
# The induced tasks migration should be done after all VMs have been restored
|
||||
# following a host reboot in AIO, hence the delay.
|
||||
################################################################################
|
||||
function move_inactive_threads_to_platform_cores {
|
||||
local tasklist
|
||||
local cmd_str=""
|
||||
|
||||
# Compile a list of non-kernel & non-vswitch/VM related threads that are not
|
||||
# on platform cores.
|
||||
# e.g. if the platform cpulist value is "0 8", the resulting command to be
|
||||
# evaluated should look like this:
|
||||
# ps-sched.sh|grep -v vswitch|awk '($10!=0 && $10!=8 && $3!=2) {if(NR>1)print $2}'
|
||||
cmd_str="ps-sched.sh|grep -v vswitch|awk '("
|
||||
for cpu_num in ${PLATFORM_CPULIST}; do
|
||||
cmd_str=$cmd_str"\$10!="${cpu_num}" && "
|
||||
done
|
||||
cmd_str=$cmd_str"\$3!=2) {if(NR>1)print \$2}'"
|
||||
echo "selection string = $cmd_str"
|
||||
tasklist=($(eval $cmd_str))
|
||||
log_debug "${TAG} There are ${#tasklist[@]} number of tasks to be moved."
|
||||
|
||||
# These sleep tasks are stuck on the wrong core(s). They need to be woken up
|
||||
# so they can be migrated to the right ones. Attaching and detaching strace
|
||||
# momentarily to the task does the trick.
|
||||
for task in ${tasklist[@]}; do
|
||||
strace -p $task 2>/dev/null &
|
||||
pid=$!
|
||||
sleep 0.1
|
||||
kill -SIGINT $pid
|
||||
done
|
||||
tasklist=($(eval $cmd_str))
|
||||
[[ ${#tasklist[@]} -eq 0 ]] && return 0 || return 1
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# The following function is called by affine-platform.sh to affine tasks to
|
||||
# all available cores during initial startup and subsequent host reboots.
|
||||
################################################################################
|
||||
function affine_tasks_to_all_cores {
|
||||
local pidlist
|
||||
local rc=0
|
||||
|
||||
if [[ "${KERNEL}" == *" RT "* ]]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
log_debug "${TAG} Affining all tasks to CPU (${FULLSET_CPUS})"
|
||||
|
||||
pidlist=$(ps --ppid 2 -p 2 --deselect -o pid= | awk '{ print $1; }')
|
||||
for pid in ${pidlist[@]}; do
|
||||
ppid=$(ps -o ppid= -p $pid |tr -d '[:space:]')
|
||||
if [ -z $ppid ] || [ $ppid -eq 2 ]; then
|
||||
continue
|
||||
fi
|
||||
log_debug "Affining pid $pid, parent pid = $ppid"
|
||||
taskset --all-tasks --pid --cpu-list ${FULLSET_CPUS} $pid &> /dev/null
|
||||
rc=$?
|
||||
[[ $rc -ne 0 ]] && log_error "Failed to set CPU affinity for pid $pid, rc=$rc"
|
||||
done
|
||||
# Write the cpu list to a temp file which will be read and removed when
|
||||
# the tasks are reaffined back to platform cores later on.
|
||||
echo ${FULLSET_CPUS} > ${TASK_AFFINING_INCOMPLETE}
|
||||
|
||||
return $rc
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# The following function can be called by any platform service that needs to
|
||||
# temporarily make use of idle VM cores to run a short-duration, service
|
||||
# critical and cpu intensive operation in AIO. For instance, sm can levearage
|
||||
# the idle cores to speed up swact activity.
|
||||
#
|
||||
# At the end of the operation, regarless of the result, the service must be
|
||||
# calling function affine_tasks_to_platform_cores to re-affine platform tasks
|
||||
# back to their assigned core(s).
|
||||
#
|
||||
# Kernel, vswitch and VM related tasks are untouched.
|
||||
################################################################################
|
||||
function affine_tasks_to_idle_cores {
|
||||
local cpulist
|
||||
local cpuocc_list
|
||||
local vswitch_pid
|
||||
local pidlist
|
||||
local idle_cpulist
|
||||
local platform_cpus
|
||||
local rc=0
|
||||
local cpu=0
|
||||
|
||||
if [ -f ${TASK_AFFINING_INCOMPLETE} ]; then
|
||||
read cpulist < ${TASK_AFFINING_INCOMPLETE}
|
||||
log_debug "${TAG} Tasks have already been affined to CPU ($cpulist)."
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [[ "${KERNEL}" == *" RT "* ]]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Compile a list of cpus with idle percentage greater than 95% in the last
|
||||
# 5 seconds.
|
||||
cpuocc_list=($(sar -P ALL 1 5|grep Average|awk '{if(NR>2)print $8}'))
|
||||
|
||||
for idle_value in ${cpuocc_list[@]}; do
|
||||
is_vswitch_core $cpu
|
||||
if [ $? -eq 1 ]; then
|
||||
cpu=$(($cpu+1))
|
||||
continue
|
||||
fi
|
||||
|
||||
is_platform_core $cpu
|
||||
if [ $? -eq 1 ]; then
|
||||
# Platform core is added to the idle list by default
|
||||
idle_cpulist=$idle_cpulist$cpu","
|
||||
else
|
||||
# Non platform core is added to the idle list if it is more than 95% idle
|
||||
[[ $(echo "$idle_value > ${IDLE_MARK}"|bc) -eq 1 ]] && idle_cpulist=$idle_cpulist$cpu","
|
||||
fi
|
||||
cpu=$(($cpu+1))
|
||||
done
|
||||
|
||||
idle_cpulist=$(echo $idle_cpulist|sed 's/.$//')
|
||||
platform_affinity_mask=$(cpulist_to_cpumap ${PLATFORM_CPUS} ${N_CPUS} \
|
||||
|awk '{print tolower($0)}')
|
||||
|
||||
log_debug "${TAG} Affining all tasks to idle CPU ($idle_cpulist)"
|
||||
|
||||
vswitch_pid=$(pgrep vswitch)
|
||||
pidlist=$(ps --ppid 2 -p 2 --deselect -o pid= | awk '{ print $1; }')
|
||||
for pid in ${pidlist[@]}; do
|
||||
ppid=$(ps -o ppid= -p $pid |tr -d '[:space:]')
|
||||
if [ -z $ppid ] || [ $ppid -eq 2 ] || [ "$pid" = "$vswitch_pid" ]; then
|
||||
continue
|
||||
fi
|
||||
pid_affinity_mask=$(taskset -p $pid | awk '{print $6}')
|
||||
if [ "${pid_affinity_mask}" == "${platform_affinity_mask}" ]; then
|
||||
# log_debug "Affining pid $pid to idle cores..."
|
||||
taskset --all-tasks --pid --cpu-list $idle_cpulist $pid &> /dev/null
|
||||
rc=$?
|
||||
[[ $rc -ne 0 ]] && log_error "Failed to set CPU affinity for pid $pid, rc=$rc"
|
||||
fi
|
||||
done
|
||||
|
||||
# Save the cpu list to the temp file which will be read and removed when
|
||||
# tasks are reaffined to the platform cores later on.
|
||||
echo $idle_cpulist > ${TASK_AFFINING_INCOMPLETE}
|
||||
return $rc
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# The following function is called by either:
|
||||
# a) nova-compute wrapper script during AIO system initial bringup or reboot
|
||||
# or
|
||||
# b) sm at the end of swact sequence
|
||||
# to re-affine management tasks back to the platform cores.
|
||||
################################################################################
|
||||
function affine_tasks_to_platform_cores {
|
||||
local cpulist
|
||||
local pidlist
|
||||
local rc=0
|
||||
local count=0
|
||||
|
||||
if [ ! -f ${TASK_AFFINING_INCOMPLETE} ]; then
|
||||
dbg_str="${TAG} Either tasks have never been affined to all/idle cores or"
|
||||
dbg_str=$dbg_str" they have already been reaffined to platform cores."
|
||||
log_debug "$dbg_str"
|
||||
return 0
|
||||
fi
|
||||
|
||||
read cpulist < ${TASK_AFFINING_INCOMPLETE}
|
||||
affinity_mask=$(cpulist_to_cpumap $cpulist ${N_CPUS}|awk '{print tolower($0)}')
|
||||
|
||||
log_debug "${TAG} Reaffining tasks to platform cores (${PLATFORM_CPUS})..."
|
||||
pidlist=$(ps --ppid 2 -p 2 --deselect -o pid= | awk '{ print $1; }')
|
||||
for pid in ${pidlist[@]}; do
|
||||
# log_debug "Processing pid $pid..."
|
||||
pid_affinity_mask=$(taskset -p $pid | awk '{print $6}')
|
||||
# Only management tasks need to be reaffined. Kernel, vswitch and VM related
|
||||
# tasks were not affined previously so they should have different affinity
|
||||
# mask(s).
|
||||
if [ "${pid_affinity_mask}" == "${affinity_mask}" ]; then
|
||||
count=$(($count+1))
|
||||
# log_debug "Affining pid $pid to platform cores..."
|
||||
taskset --all-tasks --pid --cpu-list ${PLATFORM_CPUS} $pid &> /dev/null
|
||||
rc=$?
|
||||
[[ $rc -ne 0 ]] && log_error "Failed to set CPU affinity for pid $pid, rc=$rc"
|
||||
fi
|
||||
done
|
||||
|
||||
# A workaround for lack of "end of swact" state
|
||||
fullmask=$(echo ${FULLSET_MASK} | awk '{print tolower($0)}')
|
||||
if [ "${affinity_mask}" != "${fullmask}" ]; then
|
||||
log_debug "${TAG} Schedule an audit and cleanup"
|
||||
(sleep 60; audit_and_reaffine "0x"$affinity_mask) &
|
||||
fi
|
||||
|
||||
rm -rf ${TASK_AFFINING_INCOMPLETE}
|
||||
log_debug "${TAG} $count tasks were reaffined to platform cores."
|
||||
|
||||
return $rc
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# The following function can be leveraged by cron tasks
|
||||
################################################################################
|
||||
function get_most_idle_core {
|
||||
local cpuocc_list
|
||||
local cpu=0
|
||||
local most_idle_value=${IDLE_MARK}
|
||||
local most_idle_cpu=0
|
||||
|
||||
if [[ "${KERNEL}" == *" RT "* ]]; then
|
||||
echo $cpu
|
||||
return
|
||||
fi
|
||||
|
||||
cpuocc_list=($(sar -P ALL 1 5|grep Average|awk '{if(NR>2)print $8}'))
|
||||
|
||||
for idle_value in ${cpuocc_list[@]}; do
|
||||
is_vswitch_core $cpu
|
||||
if [ $? -eq 1 ]; then
|
||||
cpu=$(($cpu+1))
|
||||
continue
|
||||
fi
|
||||
|
||||
if [ $(echo "$idle_value > $most_idle_value"|bc) -eq 1 ]; then
|
||||
most_idle_value=$idle_value
|
||||
most_idle_cpu=$cpu
|
||||
fi
|
||||
cpu=$(($cpu+1))
|
||||
done
|
||||
|
||||
echo $most_idle_cpu
|
||||
}
|
||||
8
utilities/worker-utils/worker-utils/topology
Normal file
8
utilities/worker-utils/worker-utils/topology
Normal file
@@ -0,0 +1,8 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Copyright (c) 2013-2014 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
python /usr/bin/topology.pyc
|
||||
242
utilities/worker-utils/worker-utils/topology.py
Executable file
242
utilities/worker-utils/worker-utils/topology.py
Executable file
@@ -0,0 +1,242 @@
|
||||
#!/usr/bin/env python
|
||||
################################################################################
|
||||
# Copyright (c) 2013 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
################################################################################
|
||||
#
|
||||
# topology.py -- gives a summary of logical cpu enumeration,
|
||||
# sockets, cores per package, threads per core,
|
||||
# total memory, and numa nodes
|
||||
|
||||
from __future__ import print_function
|
||||
import os
|
||||
import sys
|
||||
import re
|
||||
|
||||
class Topology(object):
|
||||
""" Build up topology information.
|
||||
(i.e. logical cpu topology, NUMA nodes, memory)
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.num_cpus = 0
|
||||
self.num_nodes = 0
|
||||
self.num_sockets = 0
|
||||
self.num_cores_per_pkg = 0
|
||||
self.num_threads_per_core = 0
|
||||
|
||||
self.topology = {}
|
||||
self.topology_idx = {}
|
||||
self.total_memory_MiB = 0
|
||||
self.total_memory_nodes_MiB = []
|
||||
|
||||
self._get_cpu_topology()
|
||||
self._get_total_memory_MiB()
|
||||
self._get_total_memory_nodes_MiB()
|
||||
|
||||
def _get_cpu_topology(self):
|
||||
'''Enumerate logical cpu topology based on parsing /proc/cpuinfo
|
||||
as function of socket_id, core_id, and thread_id. This updates
|
||||
topology and reverse index topology_idx mapping.
|
||||
|
||||
:param self
|
||||
:updates self.num_cpus - number of logical cpus
|
||||
:updates self.num_nodes - number of sockets; maps to number of numa nodes
|
||||
:updates self.topology[socket_id][core_id][thread_id] = cpu
|
||||
:updates self.topology_idx[cpu] = {'s': socket_id, 'c': core_id, 't': thread_id}
|
||||
:returns None
|
||||
'''
|
||||
|
||||
self.num_cpus = 0
|
||||
self.num_nodes = 0
|
||||
self.num_sockets = 0
|
||||
self.num_cores = 0
|
||||
self.num_threads = 0
|
||||
self.topology = {}
|
||||
self.topology_idx = {}
|
||||
|
||||
Thread_cnt = {}
|
||||
cpu = socket_id = core_id = thread_id = -1
|
||||
re_processor = re.compile(r'^[Pp]rocessor\s+:\s+(\d+)')
|
||||
re_socket = re.compile(r'^physical id\s+:\s+(\d+)')
|
||||
re_core = re.compile(r'^core id\s+:\s+(\d+)')
|
||||
|
||||
with open('/proc/cpuinfo', 'r') as infile:
|
||||
for line in infile:
|
||||
|
||||
match = re_processor.search(line)
|
||||
if match:
|
||||
cpu = int(match.group(1))
|
||||
socket_id = -1; core_id = -1; thread_id = -1
|
||||
self.num_cpus += 1
|
||||
continue
|
||||
|
||||
match = re_socket.search(line)
|
||||
if match:
|
||||
socket_id = int(match.group(1))
|
||||
continue
|
||||
|
||||
match = re_core.search(line)
|
||||
if match:
|
||||
core_id = int(match.group(1))
|
||||
|
||||
if socket_id not in Thread_cnt:
|
||||
Thread_cnt[socket_id] = {}
|
||||
if core_id not in Thread_cnt[socket_id]:
|
||||
Thread_cnt[socket_id][core_id] = 0
|
||||
else:
|
||||
Thread_cnt[socket_id][core_id] += 1
|
||||
thread_id = Thread_cnt[socket_id][core_id]
|
||||
|
||||
if socket_id not in self.topology:
|
||||
self.topology[socket_id] = {}
|
||||
if core_id not in self.topology[socket_id]:
|
||||
self.topology[socket_id][core_id] = {}
|
||||
|
||||
self.topology[socket_id][core_id][thread_id] = cpu
|
||||
self.topology_idx[cpu] = {'s': socket_id, 'c': core_id, 't': thread_id}
|
||||
continue
|
||||
self.num_nodes = len(self.topology.keys())
|
||||
|
||||
# In the case topology not detected, hard-code structures
|
||||
if self.num_nodes == 0:
|
||||
n_sockets, n_cores, n_threads = (1, self.num_cpus, 1)
|
||||
self.topology = {}
|
||||
for socket_id in range(n_sockets):
|
||||
self.topology[socket_id] = {}
|
||||
for core_id in range(n_cores):
|
||||
self.topology[socket_id][core_id] = {}
|
||||
for thread_id in range(n_threads):
|
||||
self.topology[socket_id][core_id][thread_id] = 0
|
||||
# Define Thread-Socket-Core order for logical cpu enumeration
|
||||
self.topology_idx = {}
|
||||
cpu = 0
|
||||
for thread_id in range(n_threads):
|
||||
for socket_id in range(n_sockets):
|
||||
for core_id in range(n_cores):
|
||||
self.topology[socket_id][core_id][thread_id] = cpu
|
||||
self.topology_idx[cpu] = {'s': socket_id, 'c': core_id, 't': thread_id}
|
||||
cpu += 1
|
||||
self.num_nodes = len(self.topology.keys())
|
||||
|
||||
self.num_sockets = len(self.topology.keys())
|
||||
self.num_cores_per_pkg = len(self.topology[0].keys())
|
||||
self.num_threads_per_core = len(self.topology[0][0].keys())
|
||||
|
||||
return None
|
||||
|
||||
def _get_total_memory_MiB(self):
|
||||
"""Get the total memory for VMs (MiB).
|
||||
|
||||
:updates: total memory for VMs (MiB)
|
||||
|
||||
"""
|
||||
|
||||
self.total_memory_MiB = 0
|
||||
|
||||
# Total memory
|
||||
try:
|
||||
m = open('/proc/meminfo').read().split()
|
||||
idx_Total = m.index('MemTotal:') + 1
|
||||
self.total_memory_MiB = int(m[idx_Total]) / 1024
|
||||
except IOError:
|
||||
# silently ignore IO errors (eg. file missing)
|
||||
pass
|
||||
return None
|
||||
|
||||
def _get_total_memory_nodes_MiB(self):
|
||||
"""Get the total memory per numa node for VMs (MiB).
|
||||
|
||||
:updates: total memory per numa node for VMs (MiB)
|
||||
|
||||
"""
|
||||
|
||||
self.total_memory_nodes_MiB = []
|
||||
|
||||
# Memory of each numa node (MiB)
|
||||
for node in range(self.num_nodes):
|
||||
Total_MiB = 0
|
||||
|
||||
meminfo = "/sys/devices/system/node/node%d/meminfo" % node
|
||||
try:
|
||||
m = open(meminfo).read().split()
|
||||
idx_Total = m.index('MemTotal:') + 1
|
||||
Total_MiB = int(m[idx_Total]) / 1024
|
||||
except IOError:
|
||||
# silently ignore IO errors (eg. file missing)
|
||||
pass
|
||||
|
||||
self.total_memory_nodes_MiB.append(Total_MiB)
|
||||
return None
|
||||
|
||||
def _print_cpu_topology(self):
|
||||
'''Print logical cpu topology enumeration as function of:
|
||||
socket_id, core_id, and thread_id.
|
||||
|
||||
:param self
|
||||
:returns None
|
||||
'''
|
||||
|
||||
cpu_list = self.topology_idx.keys()
|
||||
cpu_list.sort()
|
||||
total_memory_GiB = self.total_memory_MiB/1024.0
|
||||
|
||||
print('TOPOLOGY:')
|
||||
print('%16s : %5d' % ('logical cpus', self.num_cpus))
|
||||
print('%16s : %5d' % ('sockets', self.num_sockets))
|
||||
print('%16s : %5d' % ('cores_per_pkg', self.num_cores_per_pkg))
|
||||
print('%16s : %5d' % ('threads_per_core', self.num_threads_per_core))
|
||||
print('%16s : %5d' % ('numa_nodes', self.num_nodes))
|
||||
print('%16s : %5.2f %s' % ('total_memory', total_memory_GiB, 'GiB'))
|
||||
print('%16s :' % ('memory_per_node'), end=' ')
|
||||
for node in range(self.num_nodes):
|
||||
node_memory_GiB = self.total_memory_nodes_MiB[node]/1024.0
|
||||
print('%5.2f' % (node_memory_GiB), end=' ')
|
||||
print('%s' % ('GiB'))
|
||||
print('')
|
||||
|
||||
print('LOGICAL CPU TOPOLOGY:')
|
||||
print("%9s :" % 'cpu_id', end=' ')
|
||||
for cpu in cpu_list:
|
||||
print("%3d" % cpu, end=' ')
|
||||
print('')
|
||||
print("%9s :" % 'socket_id', end=' ')
|
||||
for cpu in cpu_list:
|
||||
socket_id = self.topology_idx[cpu]['s']
|
||||
print("%3d" % socket_id, end=' ')
|
||||
print('')
|
||||
print("%9s :" % 'core_id', end=' ')
|
||||
for cpu in cpu_list:
|
||||
core_id = self.topology_idx[cpu]['c']
|
||||
print("%3d" % core_id, end=' ')
|
||||
print('')
|
||||
print("%9s :" % 'thread_id', end=' ')
|
||||
for cpu in cpu_list:
|
||||
thread_id = self.topology_idx[cpu]['t']
|
||||
print("%3d" % thread_id, end=' ')
|
||||
print('')
|
||||
print('')
|
||||
|
||||
print('CORE TOPOLOGY:')
|
||||
print("%6s %9s %7s %9s %s" % ('cpu_id', 'socket_id', 'core_id', 'thread_id', 'affinity'))
|
||||
for cpu in cpu_list:
|
||||
affinity = 1<<cpu
|
||||
socket_id = self.topology_idx[cpu]['s']
|
||||
core_id = self.topology_idx[cpu]['c']
|
||||
thread_id = self.topology_idx[cpu]['t']
|
||||
print("%6d %9d %7d %9d 0x%x" \
|
||||
% (cpu, socket_id, core_id, thread_id, affinity))
|
||||
|
||||
return None
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
''' Main Program
|
||||
'''
|
||||
|
||||
# Get logical cpu topology
|
||||
topology = Topology()
|
||||
topology._print_cpu_topology()
|
||||
|
||||
sys.exit(0)
|
||||
24
utilities/worker-utils/worker-utils/worker-goenabled.sh
Normal file
24
utilities/worker-utils/worker-utils/worker-goenabled.sh
Normal file
@@ -0,0 +1,24 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Copyright (c) 2014,2016 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
#
|
||||
# worker "goenabled" check.
|
||||
#
|
||||
# If a problem was detected during configuration of worker
|
||||
# resources then the board is not allowed to enable.
|
||||
#
|
||||
WORKER_GOENABLED="/var/run/worker_goenabled"
|
||||
|
||||
source "/etc/init.d/log_functions.sh"
|
||||
source "/usr/bin/tsconfig"
|
||||
|
||||
if [ -e ${VOLATILE_WORKER_CONFIG_COMPLETE} -a ! -f ${WORKER_GOENABLED} ]; then
|
||||
log_error "Worker manifest CPU configuration check failed. Failing goenabled check."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
exit 0
|
||||
55
utilities/worker-utils/worker-utils/worker_reserved.conf
Normal file
55
utilities/worker-utils/worker-utils/worker_reserved.conf
Normal file
@@ -0,0 +1,55 @@
|
||||
################################################################################
|
||||
# Copyright (c) 2018 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
################################################################################
|
||||
# WORKER Node configuration parameters for reserved memory and physical cores
|
||||
# used by Base software and VSWITCH. These are resources that libvirt cannot use.
|
||||
#
|
||||
|
||||
################################################################################
|
||||
#
|
||||
# List of logical CPU instances available in the system. This value is used
|
||||
# for auditing purposes so that the current configuration can be checked for
|
||||
# validity against the actual number of logical CPU instances in the system.
|
||||
#
|
||||
################################################################################
|
||||
WORKER_CPU_LIST="0-1"
|
||||
|
||||
################################################################################
|
||||
#
|
||||
# List of Base software resources reserved per numa node. Each array element
|
||||
# consists of a 3-tuple formatted as: <node>:<memory>:<cores>.
|
||||
#
|
||||
# Example: To reserve 1500MB and 1 core on NUMA node0, and 1500MB and 1 core
|
||||
# on NUMA node1, the variable must be specified as follows.
|
||||
# WORKER_BASE_MEMORY=("node0:1500MB:1" "node1:1500MB:1")
|
||||
#
|
||||
################################################################################
|
||||
WORKER_BASE_RESERVED=("node0:8000MB:1" "node1:2000MB:0" "node2:2000MB:0" "node3:2000MB:0")
|
||||
|
||||
################################################################################
|
||||
#
|
||||
# List of HugeTLB memory descriptors to configure. Each array element
|
||||
# consists of a 3-tuple descriptor formatted as: <node>:<pgsize>:<pgcount>.
|
||||
# The NUMA node specified must exist and the HugeTLB pagesize must be a valid
|
||||
# value such as 2048kB or 1048576kB.
|
||||
#
|
||||
# For example, to request 256 x 2MB HugeTLB pages on NUMA node0 and node1 the
|
||||
# variable must be specified as follows.
|
||||
# WORKER_VSWITCH_MEMORY=("node0:2048kB:256" "node1:2048kB:256")
|
||||
#
|
||||
################################################################################
|
||||
WORKER_VSWITCH_MEMORY=("node0:1048576kB:1" "node1:1048576kB:1" "node2:1048576kB:1" "node3:1048576kB:1")
|
||||
|
||||
################################################################################
|
||||
#
|
||||
# List of VSWITCH physical cores reserved for VSWITCH applications.
|
||||
#
|
||||
# Example: To reserve 2 cores on NUMA node0, and 2 cores on NUMA node1, the
|
||||
# variable must be specified as follows.
|
||||
# WORKER_VSWITCH_CORES=("node0:2" "node1:2")
|
||||
#
|
||||
################################################################################
|
||||
WORKER_VSWITCH_CORES=("node0:2" "node1:0" "node2:0" "node3:0")
|
||||
Reference in New Issue
Block a user