Various testing and logging updates

- test tci with Travis
   - enable multiarch testing in Travis
   - default to out-of-tree builds
   - make changing logfile safe via RCU
   - remove redundant tests
   - remove gtester test from docker
   - convert DEBUG_MMAP to tracepoints
   - remove hand rolled glob function
   - trigger tcg re-configure when needed
 -----BEGIN PGP SIGNATURE-----
 
 iQEzBAABCgAdFiEEZoWumedRZ7yvyN81+9DbCVqeKkQFAl37M6gACgkQ+9DbCVqe
 KkQ0Rwf/d0lGDPQN1Uf0zqZRQQmDCqWVuqHhZJ5xWDjbyVT2eUwR07TvNZeUKEWX
 iO+u6S7Tv91oLjZN5WjhaiuSjtJaEzCdcpkIJAWXLP/lzse37HEwvLBsdg71y+46
 LNvBrJRPpQotdb7fjr8RgCwc1qg2Bz15ekSn7XIA175zTMmUsshLJBVhLbGNqrVm
 F2UmjB9oFJ0+nzrcEnpFmWw7xvVrX1dImZXv5C2pvuHF7efSjGwiFviTRZgDjOGs
 V7HiWRV1QcgTigncncxTMbhMTKTVKK+e7O+y0DZWt/NSrT/yLDy5rcwySpmvu6C+
 cRmh/0tMo1KAhiz8Xy8LookhVj6hdA==
 =OAkV
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/stsquad/tags/pull-tesing-and-misc-191219-1' into staging

Various testing and logging updates

  - test tci with Travis
  - enable multiarch testing in Travis
  - default to out-of-tree builds
  - make changing logfile safe via RCU
  - remove redundant tests
  - remove gtester test from docker
  - convert DEBUG_MMAP to tracepoints
  - remove hand rolled glob function
  - trigger tcg re-configure when needed

# gpg: Signature made Thu 19 Dec 2019 08:24:08 GMT
# gpg:                using RSA key 6685AE99E75167BCAFC8DF35FBD0DB095A9E2A44
# gpg: Good signature from "Alex Bennée (Master Work Key) <alex.bennee@linaro.org>" [full]
# Primary key fingerprint: 6685 AE99 E751 67BC AFC8  DF35 FBD0 DB09 5A9E 2A44

* remotes/stsquad/tags/pull-tesing-and-misc-191219-1: (25 commits)
  tests/tcg: ensure we re-configure if configure.sh is updated
  trace: replace hand-crafted pattern_glob with g_pattern_match_simple
  linux-user: convert target_munmap debug to a tracepoint
  linux-user: log page table changes under -d page
  linux-user: add target_mmap_complete tracepoint
  linux-user: convert target_mmap debug to tracepoint
  linux-user: convert target_mprotect debug to tracepoint
  travis.yml: Remove the redundant clang-with-MAIN_SOFTMMU_TARGETS entry
  docker: gtester is no longer used
  Added tests for close and change of logfile.
  Add use of RCU for qemu_logfile.
  qemu_log_lock/unlock now preserves the qemu_logfile handle.
  Add a mutex to guarantee single writer to qemu_logfile handle.
  Cleaned up flow of code in qemu_set_log(), to simplify and clarify.
  Fix double free issue in qemu_set_log_filename().
  ci: build out-of-tree
  travis.yml: Enable builds on arm64, ppc64le and s390x
  tests/test-util-filemonitor: Skip test on non-x86 Travis containers
  tests/hd-geo-test: Skip test when images can not be created
  iotests: Skip test 079 if it is not possible to create large files
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2019-12-20 14:00:49 +00:00
commit f59b31e6d0
47 changed files with 486 additions and 216 deletions

View File

@ -22,7 +22,9 @@ macos_task:
install_script: install_script:
- brew install pkg-config python gnu-sed glib pixman make sdl2 - brew install pkg-config python gnu-sed glib pixman make sdl2
script: script:
- ./configure --python=/usr/local/bin/python3 || { cat config.log; exit 1; } - mkdir build
- cd build
- ../configure --python=/usr/local/bin/python3 || { cat config.log; exit 1; }
- gmake -j$(sysctl -n hw.ncpu) - gmake -j$(sysctl -n hw.ncpu)
- gmake check -j$(sysctl -n hw.ncpu) - gmake check -j$(sysctl -n hw.ncpu)
@ -33,6 +35,8 @@ macos_xcode_task:
install_script: install_script:
- brew install pkg-config gnu-sed glib pixman make sdl2 - brew install pkg-config gnu-sed glib pixman make sdl2
script: script:
- ./configure --cc=clang || { cat config.log; exit 1; } - mkdir build
- cd build
- ../configure --cc=clang || { cat config.log; exit 1; }
- gmake -j$(sysctl -n hw.ncpu) - gmake -j$(sysctl -n hw.ncpu)
- gmake check -j$(sysctl -n hw.ncpu) - gmake check -j$(sysctl -n hw.ncpu)

View File

@ -6,7 +6,9 @@ build-system1:
script: script:
- apt-get install -y -qq libgtk-3-dev libvte-dev nettle-dev libcacard-dev - apt-get install -y -qq libgtk-3-dev libvte-dev nettle-dev libcacard-dev
libusb-dev libvde-dev libspice-protocol-dev libgl1-mesa-dev libvdeplug-dev libusb-dev libvde-dev libspice-protocol-dev libgl1-mesa-dev libvdeplug-dev
- ./configure --enable-werror --target-list="aarch64-softmmu alpha-softmmu - mkdir build
- cd build
- ../configure --enable-werror --target-list="aarch64-softmmu alpha-softmmu
cris-softmmu hppa-softmmu lm32-softmmu moxie-softmmu microblazeel-softmmu cris-softmmu hppa-softmmu lm32-softmmu moxie-softmmu microblazeel-softmmu
mips64el-softmmu m68k-softmmu ppc-softmmu riscv64-softmmu sparc-softmmu" mips64el-softmmu m68k-softmmu ppc-softmmu riscv64-softmmu sparc-softmmu"
- make -j2 - make -j2
@ -16,7 +18,9 @@ build-system2:
script: script:
- apt-get install -y -qq libsdl2-dev libgcrypt-dev libbrlapi-dev libaio-dev - apt-get install -y -qq libsdl2-dev libgcrypt-dev libbrlapi-dev libaio-dev
libfdt-dev liblzo2-dev librdmacm-dev libibverbs-dev libibumad-dev libfdt-dev liblzo2-dev librdmacm-dev libibverbs-dev libibumad-dev
- ./configure --enable-werror --target-list="tricore-softmmu unicore32-softmmu - mkdir build
- cd build
- ../configure --enable-werror --target-list="tricore-softmmu unicore32-softmmu
microblaze-softmmu mips-softmmu riscv32-softmmu s390x-softmmu sh4-softmmu microblaze-softmmu mips-softmmu riscv32-softmmu s390x-softmmu sh4-softmmu
sparc64-softmmu x86_64-softmmu xtensa-softmmu nios2-softmmu or1k-softmmu" sparc64-softmmu x86_64-softmmu xtensa-softmmu nios2-softmmu or1k-softmmu"
- make -j2 - make -j2
@ -24,7 +28,9 @@ build-system2:
build-disabled: build-disabled:
script: script:
- ./configure --enable-werror --disable-rdma --disable-slirp --disable-curl - mkdir build
- cd build
- ../configure --enable-werror --disable-rdma --disable-slirp --disable-curl
--disable-capstone --disable-live-block-migration --disable-glusterfs --disable-capstone --disable-live-block-migration --disable-glusterfs
--disable-replication --disable-coroutine-pool --disable-smartcard --disable-replication --disable-coroutine-pool --disable-smartcard
--disable-guest-agent --disable-curses --disable-libxml2 --disable-tpm --disable-guest-agent --disable-curses --disable-libxml2 --disable-tpm
@ -37,7 +43,9 @@ build-disabled:
build-tcg-disabled: build-tcg-disabled:
script: script:
- apt-get install -y -qq clang libgtk-3-dev libusb-dev - apt-get install -y -qq clang libgtk-3-dev libusb-dev
- ./configure --cc=clang --enable-werror --disable-tcg --audio-drv-list="" - mkdir build
- cd build
- ../configure --cc=clang --enable-werror --disable-tcg --audio-drv-list=""
- make -j2 - make -j2
- make check-unit - make check-unit
- make check-qapi-schema - make check-qapi-schema
@ -52,7 +60,9 @@ build-tcg-disabled:
build-user: build-user:
script: script:
- ./configure --enable-werror --disable-system --disable-guest-agent - mkdir build
- cd build
- ../configure --enable-werror --disable-system --disable-guest-agent
--disable-capstone --disable-slirp --disable-fdt --disable-capstone --disable-slirp --disable-fdt
- make -j2 - make -j2
- make run-tcg-tests-i386-linux-user run-tcg-tests-x86_64-linux-user - make run-tcg-tests-i386-linux-user run-tcg-tests-x86_64-linux-user
@ -61,7 +71,9 @@ build-clang:
script: script:
- apt-get install -y -qq clang libsdl2-dev libattr1-dev libcap-ng-dev - apt-get install -y -qq clang libsdl2-dev libattr1-dev libcap-ng-dev
xfslibs-dev libiscsi-dev libnfs-dev libseccomp-dev gnutls-dev librbd-dev xfslibs-dev libiscsi-dev libnfs-dev libseccomp-dev gnutls-dev librbd-dev
- ./configure --cc=clang --cxx=clang++ --enable-werror - mkdir build
- cd build
- ../configure --cc=clang --cxx=clang++ --enable-werror
--target-list="alpha-softmmu arm-softmmu m68k-softmmu mips64-softmmu --target-list="alpha-softmmu arm-softmmu m68k-softmmu mips64-softmmu
ppc-softmmu s390x-softmmu x86_64-softmmu arm-linux-user" ppc-softmmu s390x-softmmu x86_64-softmmu arm-linux-user"
- make -j2 - make -j2
@ -70,7 +82,9 @@ build-clang:
build-tci: build-tci:
script: script:
- TARGETS="aarch64 alpha arm hppa m68k microblaze moxie ppc64 s390x x86_64" - TARGETS="aarch64 alpha arm hppa m68k microblaze moxie ppc64 s390x x86_64"
- ./configure --enable-tcg-interpreter - mkdir build
- cd build
- ../configure --enable-tcg-interpreter
--target-list="$(for tg in $TARGETS; do echo -n ${tg}'-softmmu '; done)" --target-list="$(for tg in $TARGETS; do echo -n ${tg}'-softmmu '; done)"
- make -j2 - make -j2
- make tests/boot-serial-test tests/cdrom-test tests/pxe-test - make tests/boot-serial-test tests/cdrom-test tests/pxe-test

View File

@ -35,5 +35,7 @@ build:
options: "-e HOME=/root" options: "-e HOME=/root"
ci: ci:
- unset CC - unset CC
- ./configure ${QEMU_CONFIGURE_OPTS} --target-list=${TARGET_LIST} - mkdir build
- cd build
- ../configure ${QEMU_CONFIGURE_OPTS} --target-list=${TARGET_LIST}
- make -j$(($(getconf _NPROCESSORS_ONLN) + 1)) - make -j$(($(getconf _NPROCESSORS_ONLN) + 1))

View File

@ -73,8 +73,8 @@ notifications:
env: env:
global: global:
- SRC_DIR="." - SRC_DIR=".."
- BUILD_DIR="." - BUILD_DIR="build"
- BASE_CONFIG="--disable-docs --disable-tools" - BASE_CONFIG="--disable-docs --disable-tools"
- TEST_CMD="make check V=1" - TEST_CMD="make check V=1"
# This is broadly a list of "mainline" softmmu targets which have support across the major distros # This is broadly a list of "mainline" softmmu targets which have support across the major distros
@ -180,18 +180,13 @@ matrix:
compiler: clang compiler: clang
- env:
- CONFIG="--disable-user --target-list=${MAIN_SOFTMMU_TARGETS}"
- CACHE_NAME="${TRAVIS_BRANCH}-linux-clang-default"
compiler: clang
- env: - env:
- CONFIG="--target-list=${MAIN_SOFTMMU_TARGETS} " - CONFIG="--target-list=${MAIN_SOFTMMU_TARGETS} "
- CACHE_NAME="${TRAVIS_BRANCH}-linux-clang-sanitize" - CACHE_NAME="${TRAVIS_BRANCH}-linux-clang-sanitize"
compiler: clang compiler: clang
before_script: before_script:
- ./configure ${CONFIG} --extra-cflags="-fsanitize=undefined -Werror" || { cat config.log && exit 1; } - mkdir -p ${BUILD_DIR} && cd ${BUILD_DIR}
- ${SRC_DIR}/configure ${CONFIG} --extra-cflags="-fsanitize=undefined -Werror" || { cat config.log && exit 1; }
- env: - env:
@ -214,10 +209,11 @@ matrix:
- TEST_CMD="" - TEST_CMD=""
# We manually include builds which we disable "make check" for # Check the TCG interpreter (TCI)
- env: - env:
- CONFIG="--enable-debug --enable-tcg-interpreter" - CONFIG="--enable-debug-tcg --enable-tcg-interpreter --disable-kvm --disable-containers
- TEST_CMD="" --target-list=alpha-softmmu,arm-softmmu,hppa-softmmu,m68k-softmmu,microblaze-softmmu,moxie-softmmu,ppc-softmmu,s390x-softmmu,x86_64-softmmu"
- TEST_CMD="make check-qtest check-tcg V=1"
# We don't need to exercise every backend with every front-end # We don't need to exercise every backend with every front-end
@ -322,7 +318,8 @@ matrix:
- CONFIG="--cc=gcc-9 --cxx=g++-9 --disable-pie --disable-linux-user" - CONFIG="--cc=gcc-9 --cxx=g++-9 --disable-pie --disable-linux-user"
- TEST_CMD="" - TEST_CMD=""
before_script: before_script:
- ./configure ${CONFIG} --extra-cflags="-g3 -O0 -Wno-error=stringop-truncation -fsanitize=thread -fuse-ld=gold" || { cat config.log && exit 1; } - mkdir -p ${BUILD_DIR} && cd ${BUILD_DIR}
- ${SRC_DIR}/configure ${CONFIG} --extra-cflags="-g3 -O0 -Wno-error=stringop-truncation -fsanitize=thread -fuse-ld=gold" || { cat config.log && exit 1; }
# Run check-tcg against linux-user # Run check-tcg against linux-user
@ -353,6 +350,92 @@ matrix:
- TEST_CMD="make -j3 check-tcg V=1" - TEST_CMD="make -j3 check-tcg V=1"
- CACHE_NAME="${TRAVIS_BRANCH}-linux-gcc-debug-tcg" - CACHE_NAME="${TRAVIS_BRANCH}-linux-gcc-debug-tcg"
- arch: arm64
dist: xenial
addons:
apt_packages:
- libaio-dev
- libattr1-dev
- libbrlapi-dev
- libcap-ng-dev
- libgcrypt20-dev
- libgnutls28-dev
- libgtk-3-dev
- libiscsi-dev
- liblttng-ust-dev
- libncurses5-dev
- libnfs-dev
- libnss3-dev
- libpixman-1-dev
- libpng-dev
- librados-dev
- libsdl2-dev
- libseccomp-dev
- liburcu-dev
- libusb-1.0-0-dev
- libvdeplug-dev
- libvte-2.91-dev
env:
- TEST_CMD="make check check-tcg V=1"
- CONFIG="--disable-containers --target-list=${MAIN_SOFTMMU_TARGETS}"
- arch: ppc64le
dist: xenial
addons:
apt_packages:
- libaio-dev
- libattr1-dev
- libbrlapi-dev
- libcap-ng-dev
- libgcrypt20-dev
- libgnutls28-dev
- libgtk-3-dev
- libiscsi-dev
- liblttng-ust-dev
- libncurses5-dev
- libnfs-dev
- libnss3-dev
- libpixman-1-dev
- libpng-dev
- librados-dev
- libsdl2-dev
- libseccomp-dev
- liburcu-dev
- libusb-1.0-0-dev
- libvdeplug-dev
- libvte-2.91-dev
env:
- TEST_CMD="make check check-tcg V=1"
- CONFIG="--disable-containers --target-list=${MAIN_SOFTMMU_TARGETS},ppc64le-linux-user"
- arch: s390x
dist: bionic
addons:
apt_packages:
- libaio-dev
- libattr1-dev
- libbrlapi-dev
- libcap-ng-dev
- libgcrypt20-dev
- libgnutls28-dev
- libgtk-3-dev
- libiscsi-dev
- liblttng-ust-dev
- libncurses5-dev
- libnfs-dev
- libnss3-dev
- libpixman-1-dev
- libpng-dev
- librados-dev
- libsdl2-dev
- libseccomp-dev
- liburcu-dev
- libusb-1.0-0-dev
- libvdeplug-dev
- libvte-2.91-dev
env:
- TEST_CMD="make check check-tcg V=1"
- CONFIG="--disable-containers --target-list=${MAIN_SOFTMMU_TARGETS},s390x-linux-user"
# Release builds # Release builds
# The make-release script expect a QEMU version, so our tag must start with a 'v'. # The make-release script expect a QEMU version, so our tag must start with a 'v'.
@ -373,5 +456,6 @@ matrix:
- make -C ${SRC_DIR} qemu-${QEMU_VERSION}.tar.bz2 - make -C ${SRC_DIR} qemu-${QEMU_VERSION}.tar.bz2
- ls -l ${SRC_DIR}/qemu-${QEMU_VERSION}.tar.bz2 - ls -l ${SRC_DIR}/qemu-${QEMU_VERSION}.tar.bz2
- tar -xf ${SRC_DIR}/qemu-${QEMU_VERSION}.tar.bz2 && cd qemu-${QEMU_VERSION} - tar -xf ${SRC_DIR}/qemu-${QEMU_VERSION}.tar.bz2 && cd qemu-${QEMU_VERSION}
- ./configure ${BASE_CONFIG} ${CONFIG} || { cat config.log && exit 1; } - mkdir -p release-build && cd release-build
- ../configure ${BASE_CONFIG} ${CONFIG} || { cat config.log && exit 1; }
- make install - make install

View File

@ -156,7 +156,7 @@ static inline tcg_target_ulong cpu_tb_exec(CPUState *cpu, TranslationBlock *itb)
#if defined(DEBUG_DISAS) #if defined(DEBUG_DISAS)
if (qemu_loglevel_mask(CPU_LOG_TB_CPU) if (qemu_loglevel_mask(CPU_LOG_TB_CPU)
&& qemu_log_in_addr_range(itb->pc)) { && qemu_log_in_addr_range(itb->pc)) {
qemu_log_lock(); FILE *logfile = qemu_log_lock();
int flags = 0; int flags = 0;
if (qemu_loglevel_mask(CPU_LOG_TB_FPU)) { if (qemu_loglevel_mask(CPU_LOG_TB_FPU)) {
flags |= CPU_DUMP_FPU; flags |= CPU_DUMP_FPU;
@ -165,7 +165,7 @@ static inline tcg_target_ulong cpu_tb_exec(CPUState *cpu, TranslationBlock *itb)
flags |= CPU_DUMP_CCOP; flags |= CPU_DUMP_CCOP;
#endif #endif
log_cpu_state(cpu, flags); log_cpu_state(cpu, flags);
qemu_log_unlock(); qemu_log_unlock(logfile);
} }
#endif /* DEBUG_DISAS */ #endif /* DEBUG_DISAS */

View File

@ -1804,7 +1804,7 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
#ifdef DEBUG_DISAS #ifdef DEBUG_DISAS
if (qemu_loglevel_mask(CPU_LOG_TB_OUT_ASM) && if (qemu_loglevel_mask(CPU_LOG_TB_OUT_ASM) &&
qemu_log_in_addr_range(tb->pc)) { qemu_log_in_addr_range(tb->pc)) {
qemu_log_lock(); FILE *logfile = qemu_log_lock();
qemu_log("OUT: [size=%d]\n", gen_code_size); qemu_log("OUT: [size=%d]\n", gen_code_size);
if (tcg_ctx->data_gen_ptr) { if (tcg_ctx->data_gen_ptr) {
size_t code_size = tcg_ctx->data_gen_ptr - tb->tc.ptr; size_t code_size = tcg_ctx->data_gen_ptr - tb->tc.ptr;
@ -1829,7 +1829,7 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
} }
qemu_log("\n"); qemu_log("\n");
qemu_log_flush(); qemu_log_flush();
qemu_log_unlock(); qemu_log_unlock(logfile);
} }
#endif #endif

View File

@ -138,11 +138,11 @@ void translator_loop(const TranslatorOps *ops, DisasContextBase *db,
#ifdef DEBUG_DISAS #ifdef DEBUG_DISAS
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM) if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
&& qemu_log_in_addr_range(db->pc_first)) { && qemu_log_in_addr_range(db->pc_first)) {
qemu_log_lock(); FILE *logfile = qemu_log_lock();
qemu_log("----------------\n"); qemu_log("----------------\n");
ops->disas_log(db, cpu); ops->disas_log(db, cpu);
qemu_log("\n"); qemu_log("\n");
qemu_log_unlock(); qemu_log_unlock(logfile);
} }
#endif #endif
} }

View File

@ -963,7 +963,7 @@ int main(int argc, char **argv)
if (qemu_loglevel_mask(CPU_LOG_PAGE)) { if (qemu_loglevel_mask(CPU_LOG_PAGE)) {
qemu_log("guest_base 0x%lx\n", guest_base); qemu_log("guest_base 0x%lx\n", guest_base);
log_page_dump(); log_page_dump("binary load");
qemu_log("start_brk 0x" TARGET_ABI_FMT_lx "\n", info->start_brk); qemu_log("start_brk 0x" TARGET_ABI_FMT_lx "\n", info->start_brk);
qemu_log("end_code 0x" TARGET_ABI_FMT_lx "\n", info->end_code); qemu_log("end_code 0x" TARGET_ABI_FMT_lx "\n", info->end_code);

9
configure vendored
View File

@ -302,6 +302,7 @@ audio_win_int=""
libs_qga="" libs_qga=""
debug_info="yes" debug_info="yes"
stack_protector="" stack_protector=""
use_containers="yes"
if test -e "$source_path/.git" if test -e "$source_path/.git"
then then
@ -1535,6 +1536,10 @@ for opt do
;; ;;
--disable-plugins) plugins="no" --disable-plugins) plugins="no"
;; ;;
--enable-containers) use_containers="yes"
;;
--disable-containers) use_containers="no"
;;
*) *)
echo "ERROR: unknown option $opt" echo "ERROR: unknown option $opt"
echo "Try '$0 --help' for more information" echo "Try '$0 --help' for more information"
@ -1718,6 +1723,7 @@ Advanced options (experts only):
track the maximum stack usage of stacks created by qemu_alloc_stack track the maximum stack usage of stacks created by qemu_alloc_stack
--enable-plugins --enable-plugins
enable plugins via shared library loading enable plugins via shared library loading
--disable-containers don't use containers for cross-building
Optional features, enabled with --enable-FEATURE and Optional features, enabled with --enable-FEATURE and
disabled with --disable-FEATURE, default is enabled if available: disabled with --disable-FEATURE, default is enabled if available:
@ -6399,6 +6405,7 @@ else
echo "local state directory queried at runtime" echo "local state directory queried at runtime"
echo "Windows SDK $win_sdk" echo "Windows SDK $win_sdk"
fi fi
echo "Build directory $(pwd)"
echo "Source path $source_path" echo "Source path $source_path"
echo "GIT binary $git" echo "GIT binary $git"
echo "GIT submodules $git_submodules" echo "GIT submodules $git_submodules"
@ -7996,7 +8003,7 @@ done
(for i in $cross_cc_vars; do (for i in $cross_cc_vars; do
export $i export $i
done done
export target_list source_path export target_list source_path use_containers
$source_path/tests/tcg/configure.sh) $source_path/tests/tcg/configure.sh)
# temporary config to build submodules # temporary config to build submodules

View File

@ -418,13 +418,15 @@ access, so they SHOULD NOT be exposed to external interfaces if you are
concerned about attackers taking control of the guest and potentially concerned about attackers taking control of the guest and potentially
exploiting a QEMU security bug to compromise the host. exploiting a QEMU security bug to compromise the host.
QEMU binary QEMU binaries
----------- -------------
By default, qemu-system-x86_64 is searched in $PATH to run the guest. If there By default, qemu-system-x86_64 is searched in $PATH to run the guest. If there
isn't one, or if it is older than 2.10, the test won't work. In this case, isn't one, or if it is older than 2.10, the test won't work. In this case,
provide the QEMU binary in env var: ``QEMU=/path/to/qemu-2.10+``. provide the QEMU binary in env var: ``QEMU=/path/to/qemu-2.10+``.
Likewise the path to qemu-img can be set in QEMU_IMG environment variable.
Make jobs Make jobs
--------- ---------

4
exec.c
View File

@ -1225,13 +1225,13 @@ void cpu_abort(CPUState *cpu, const char *fmt, ...)
fprintf(stderr, "\n"); fprintf(stderr, "\n");
cpu_dump_state(cpu, stderr, CPU_DUMP_FPU | CPU_DUMP_CCOP); cpu_dump_state(cpu, stderr, CPU_DUMP_FPU | CPU_DUMP_CCOP);
if (qemu_log_separate()) { if (qemu_log_separate()) {
qemu_log_lock(); FILE *logfile = qemu_log_lock();
qemu_log("qemu: fatal: "); qemu_log("qemu: fatal: ");
qemu_log_vprintf(fmt, ap2); qemu_log_vprintf(fmt, ap2);
qemu_log("\n"); qemu_log("\n");
log_cpu_state(cpu, CPU_DUMP_FPU | CPU_DUMP_CCOP); log_cpu_state(cpu, CPU_DUMP_FPU | CPU_DUMP_CCOP);
qemu_log_flush(); qemu_log_flush();
qemu_log_unlock(); qemu_log_unlock(logfile);
qemu_log_close(); qemu_log_close();
} }
va_end(ap2); va_end(ap2);

View File

@ -247,8 +247,8 @@ int can_sja_accept_filter(CanSJA1000State *s,
static void can_display_msg(const char *prefix, const qemu_can_frame *msg) static void can_display_msg(const char *prefix, const qemu_can_frame *msg)
{ {
int i; int i;
FILE *logfile = qemu_log_lock();
qemu_log_lock();
qemu_log("%s%03X [%01d] %s %s", qemu_log("%s%03X [%01d] %s %s",
prefix, prefix,
msg->can_id & QEMU_CAN_EFF_MASK, msg->can_id & QEMU_CAN_EFF_MASK,
@ -261,7 +261,7 @@ static void can_display_msg(const char *prefix, const qemu_can_frame *msg)
} }
qemu_log("\n"); qemu_log("\n");
qemu_log_flush(); qemu_log_flush();
qemu_log_unlock(); qemu_log_unlock(logfile);
} }
static void buff2frame_pel(const uint8_t *buff, qemu_can_frame *frame) static void buff2frame_pel(const uint8_t *buff, qemu_can_frame *frame)

View File

@ -15,8 +15,15 @@
*/ */
static inline void log_cpu_state(CPUState *cpu, int flags) static inline void log_cpu_state(CPUState *cpu, int flags)
{ {
QemuLogFile *logfile;
if (qemu_log_enabled()) { if (qemu_log_enabled()) {
cpu_dump_state(cpu, qemu_logfile, flags); rcu_read_lock();
logfile = atomic_rcu_read(&qemu_logfile);
if (logfile) {
cpu_dump_state(cpu, logfile->fd, flags);
}
rcu_read_unlock();
} }
} }
@ -40,19 +47,36 @@ static inline void log_cpu_state_mask(int mask, CPUState *cpu, int flags)
static inline void log_target_disas(CPUState *cpu, target_ulong start, static inline void log_target_disas(CPUState *cpu, target_ulong start,
target_ulong len) target_ulong len)
{ {
target_disas(qemu_logfile, cpu, start, len); QemuLogFile *logfile;
rcu_read_lock();
logfile = atomic_rcu_read(&qemu_logfile);
if (logfile) {
target_disas(logfile->fd, cpu, start, len);
}
rcu_read_unlock();
} }
static inline void log_disas(void *code, unsigned long size) static inline void log_disas(void *code, unsigned long size)
{ {
disas(qemu_logfile, code, size); QemuLogFile *logfile;
rcu_read_lock();
logfile = atomic_rcu_read(&qemu_logfile);
if (logfile) {
disas(logfile->fd, code, size);
}
rcu_read_unlock();
} }
#if defined(CONFIG_USER_ONLY) #if defined(CONFIG_USER_ONLY)
/* page_dump() output to the log file: */ /* page_dump() output to the log file: */
static inline void log_page_dump(void) static inline void log_page_dump(const char *operation)
{ {
page_dump(qemu_logfile); FILE *logfile = qemu_log_lock();
if (logfile) {
qemu_log("page layout changed following %s\n", operation);
page_dump(logfile);
}
qemu_log_unlock(logfile);
} }
#endif #endif
#endif #endif

View File

@ -3,9 +3,16 @@
/* A small part of this API is split into its own header */ /* A small part of this API is split into its own header */
#include "qemu/log-for-trace.h" #include "qemu/log-for-trace.h"
#include "qemu/rcu.h"
typedef struct QemuLogFile {
struct rcu_head rcu;
FILE *fd;
} QemuLogFile;
/* Private global variable, don't use */ /* Private global variable, don't use */
extern FILE *qemu_logfile; extern QemuLogFile *qemu_logfile;
/* /*
* The new API: * The new API:
@ -25,7 +32,16 @@ static inline bool qemu_log_enabled(void)
*/ */
static inline bool qemu_log_separate(void) static inline bool qemu_log_separate(void)
{ {
return qemu_logfile != NULL && qemu_logfile != stderr; QemuLogFile *logfile;
bool res = false;
rcu_read_lock();
logfile = atomic_rcu_read(&qemu_logfile);
if (logfile && logfile->fd != stderr) {
res = true;
}
rcu_read_unlock();
return res;
} }
#define CPU_LOG_TB_OUT_ASM (1 << 0) #define CPU_LOG_TB_OUT_ASM (1 << 0)
@ -53,14 +69,25 @@ static inline bool qemu_log_separate(void)
* qemu_loglevel is never set when qemu_logfile is unset. * qemu_loglevel is never set when qemu_logfile is unset.
*/ */
static inline void qemu_log_lock(void) static inline FILE *qemu_log_lock(void)
{ {
qemu_flockfile(qemu_logfile); QemuLogFile *logfile;
rcu_read_lock();
logfile = atomic_rcu_read(&qemu_logfile);
if (logfile) {
qemu_flockfile(logfile->fd);
return logfile->fd;
} else {
return NULL;
}
} }
static inline void qemu_log_unlock(void) static inline void qemu_log_unlock(FILE *fd)
{ {
qemu_funlockfile(qemu_logfile); if (fd) {
qemu_funlockfile(fd);
}
rcu_read_unlock();
} }
/* Logging functions: */ /* Logging functions: */
@ -70,9 +97,14 @@ static inline void qemu_log_unlock(void)
static inline void GCC_FMT_ATTR(1, 0) static inline void GCC_FMT_ATTR(1, 0)
qemu_log_vprintf(const char *fmt, va_list va) qemu_log_vprintf(const char *fmt, va_list va)
{ {
if (qemu_logfile) { QemuLogFile *logfile;
vfprintf(qemu_logfile, fmt, va);
rcu_read_lock();
logfile = atomic_rcu_read(&qemu_logfile);
if (logfile) {
vfprintf(logfile->fd, fmt, va);
} }
rcu_read_unlock();
} }
/* log only if a bit is set on the current loglevel mask: /* log only if a bit is set on the current loglevel mask:

View File

@ -826,7 +826,7 @@ int main(int argc, char **argv, char **envp)
if (qemu_loglevel_mask(CPU_LOG_PAGE)) { if (qemu_loglevel_mask(CPU_LOG_PAGE)) {
qemu_log("guest_base 0x%lx\n", guest_base); qemu_log("guest_base 0x%lx\n", guest_base);
log_page_dump(); log_page_dump("binary load");
qemu_log("start_brk 0x" TARGET_ABI_FMT_lx "\n", info->start_brk); qemu_log("start_brk 0x" TARGET_ABI_FMT_lx "\n", info->start_brk);
qemu_log("end_code 0x" TARGET_ABI_FMT_lx "\n", info->end_code); qemu_log("end_code 0x" TARGET_ABI_FMT_lx "\n", info->end_code);

View File

@ -17,11 +17,10 @@
* along with this program; if not, see <http://www.gnu.org/licenses/>. * along with this program; if not, see <http://www.gnu.org/licenses/>.
*/ */
#include "qemu/osdep.h" #include "qemu/osdep.h"
#include "trace.h"
#include "exec/log.h"
#include "qemu.h" #include "qemu.h"
//#define DEBUG_MMAP
static pthread_mutex_t mmap_mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t mmap_mutex = PTHREAD_MUTEX_INITIALIZER;
static __thread int mmap_lock_count; static __thread int mmap_lock_count;
@ -66,13 +65,7 @@ int target_mprotect(abi_ulong start, abi_ulong len, int prot)
abi_ulong end, host_start, host_end, addr; abi_ulong end, host_start, host_end, addr;
int prot1, ret; int prot1, ret;
#ifdef DEBUG_MMAP trace_target_mprotect(start, len, prot);
printf("mprotect: start=0x" TARGET_ABI_FMT_lx
"len=0x" TARGET_ABI_FMT_lx " prot=%c%c%c\n", start, len,
prot & PROT_READ ? 'r' : '-',
prot & PROT_WRITE ? 'w' : '-',
prot & PROT_EXEC ? 'x' : '-');
#endif
if ((start & ~TARGET_PAGE_MASK) != 0) if ((start & ~TARGET_PAGE_MASK) != 0)
return -TARGET_EINVAL; return -TARGET_EINVAL;
@ -369,32 +362,7 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
abi_ulong ret, end, real_start, real_end, retaddr, host_offset, host_len; abi_ulong ret, end, real_start, real_end, retaddr, host_offset, host_len;
mmap_lock(); mmap_lock();
#ifdef DEBUG_MMAP trace_target_mmap(start, len, prot, flags, fd, offset);
{
printf("mmap: start=0x" TARGET_ABI_FMT_lx
" len=0x" TARGET_ABI_FMT_lx " prot=%c%c%c flags=",
start, len,
prot & PROT_READ ? 'r' : '-',
prot & PROT_WRITE ? 'w' : '-',
prot & PROT_EXEC ? 'x' : '-');
if (flags & MAP_FIXED)
printf("MAP_FIXED ");
if (flags & MAP_ANONYMOUS)
printf("MAP_ANON ");
switch(flags & MAP_TYPE) {
case MAP_PRIVATE:
printf("MAP_PRIVATE ");
break;
case MAP_SHARED:
printf("MAP_SHARED ");
break;
default:
printf("[MAP_TYPE=0x%x] ", flags & MAP_TYPE);
break;
}
printf("fd=%d offset=" TARGET_ABI_FMT_lx "\n", fd, offset);
}
#endif
if (!len) { if (!len) {
errno = EINVAL; errno = EINVAL;
@ -569,11 +537,10 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
the_end1: the_end1:
page_set_flags(start, start + len, prot | PAGE_VALID); page_set_flags(start, start + len, prot | PAGE_VALID);
the_end: the_end:
#ifdef DEBUG_MMAP trace_target_mmap_complete(start);
printf("ret=0x" TARGET_ABI_FMT_lx "\n", start); if (qemu_loglevel_mask(CPU_LOG_PAGE)) {
page_dump(stdout); log_page_dump(__func__);
printf("\n"); }
#endif
tb_invalidate_phys_range(start, start + len); tb_invalidate_phys_range(start, start + len);
mmap_unlock(); mmap_unlock();
return start; return start;
@ -628,11 +595,8 @@ int target_munmap(abi_ulong start, abi_ulong len)
abi_ulong end, real_start, real_end, addr; abi_ulong end, real_start, real_end, addr;
int prot, ret; int prot, ret;
#ifdef DEBUG_MMAP trace_target_munmap(start, len);
printf("munmap: start=0x" TARGET_ABI_FMT_lx " len=0x"
TARGET_ABI_FMT_lx "\n",
start, len);
#endif
if (start & ~TARGET_PAGE_MASK) if (start & ~TARGET_PAGE_MASK)
return -TARGET_EINVAL; return -TARGET_EINVAL;
len = TARGET_PAGE_ALIGN(len); len = TARGET_PAGE_ALIGN(len);

View File

@ -11,3 +11,9 @@ user_handle_signal(void *env, int target_sig) "env=%p signal %d"
user_host_signal(void *env, int host_sig, int target_sig) "env=%p signal %d (target %d(" user_host_signal(void *env, int host_sig, int target_sig) "env=%p signal %d (target %d("
user_queue_signal(void *env, int target_sig) "env=%p signal %d" user_queue_signal(void *env, int target_sig) "env=%p signal %d"
user_s390x_restore_sigregs(void *env, uint64_t sc_psw_addr, uint64_t env_psw_addr) "env=%p frame psw.addr 0x%"PRIx64 " current psw.addr 0x%"PRIx64 user_s390x_restore_sigregs(void *env, uint64_t sc_psw_addr, uint64_t env_psw_addr) "env=%p frame psw.addr 0x%"PRIx64 " current psw.addr 0x%"PRIx64
# mmap.c
target_mprotect(uint64_t start, uint64_t len, int flags) "start=0x%"PRIx64 " len=0x%"PRIx64 " prot=0x%x"
target_mmap(uint64_t start, uint64_t len, int pflags, int mflags, int fd, uint64_t offset) "start=0x%"PRIx64 " len=0x%"PRIx64 " prot=0x%x flags=0x%x fd=%d offset=0x%"PRIx64
target_mmap_complete(uint64_t retaddr) "retaddr=0x%"PRIx64
target_munmap(uint64_t start, uint64_t len) "start=0x%"PRIx64" len=0x%"PRIx64

View File

@ -76,8 +76,7 @@ QEMU_BUILD_BUG_ON(offsetof(qemu_can_frame, data)
static void can_host_socketcan_display_msg(struct qemu_can_frame *msg) static void can_host_socketcan_display_msg(struct qemu_can_frame *msg)
{ {
int i; int i;
FILE *logfile = qemu_log_lock();
qemu_log_lock();
qemu_log("[cansocketcan]: %03X [%01d] %s %s", qemu_log("[cansocketcan]: %03X [%01d] %s %s",
msg->can_id & QEMU_CAN_EFF_MASK, msg->can_id & QEMU_CAN_EFF_MASK,
msg->can_dlc, msg->can_dlc,
@ -89,7 +88,7 @@ static void can_host_socketcan_display_msg(struct qemu_can_frame *msg)
} }
qemu_log("\n"); qemu_log("\n");
qemu_log_flush(); qemu_log_flush();
qemu_log_unlock(); qemu_log_unlock(logfile);
} }
static void can_host_socketcan_read(void *opaque) static void can_host_socketcan_read(void *opaque)

View File

@ -3273,11 +3273,11 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
#if !DISAS_CRIS #if !DISAS_CRIS
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM) if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
&& qemu_log_in_addr_range(pc_start)) { && qemu_log_in_addr_range(pc_start)) {
qemu_log_lock(); FILE *logfile = qemu_log_lock();
qemu_log("--------------\n"); qemu_log("--------------\n");
qemu_log("IN: %s\n", lookup_symbol(pc_start)); qemu_log("IN: %s\n", lookup_symbol(pc_start));
log_target_disas(cs, pc_start, dc->pc - pc_start); log_target_disas(cs, pc_start, dc->pc - pc_start);
qemu_log_unlock(); qemu_log_unlock(logfile);
} }
#endif #endif
#endif #endif

View File

@ -2502,14 +2502,15 @@ static void gen_unknown_opcode(CPUX86State *env, DisasContext *s)
gen_illegal_opcode(s); gen_illegal_opcode(s);
if (qemu_loglevel_mask(LOG_UNIMP)) { if (qemu_loglevel_mask(LOG_UNIMP)) {
FILE *logfile = qemu_log_lock();
target_ulong pc = s->pc_start, end = s->pc; target_ulong pc = s->pc_start, end = s->pc;
qemu_log_lock();
qemu_log("ILLOPC: " TARGET_FMT_lx ":", pc); qemu_log("ILLOPC: " TARGET_FMT_lx ":", pc);
for (; pc < end; ++pc) { for (; pc < end; ++pc) {
qemu_log(" %02x", cpu_ldub_code(env, pc)); qemu_log(" %02x", cpu_ldub_code(env, pc));
} }
qemu_log("\n"); qemu_log("\n");
qemu_log_unlock(); qemu_log_unlock(logfile);
} }
} }

View File

@ -1137,10 +1137,10 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
#ifdef DEBUG_DISAS #ifdef DEBUG_DISAS
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM) if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
&& qemu_log_in_addr_range(pc_start)) { && qemu_log_in_addr_range(pc_start)) {
qemu_log_lock(); FILE *logfile = qemu_log_lock();
qemu_log("\n"); qemu_log("\n");
log_target_disas(cs, pc_start, dc->pc - pc_start); log_target_disas(cs, pc_start, dc->pc - pc_start);
qemu_log_unlock(); qemu_log_unlock(logfile);
} }
#endif #endif
} }

View File

@ -1765,10 +1765,10 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
#if !SIM_COMPAT #if !SIM_COMPAT
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM) if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
&& qemu_log_in_addr_range(pc_start)) { && qemu_log_in_addr_range(pc_start)) {
qemu_log_lock(); FILE *logfile = qemu_log_lock();
qemu_log("--------------\n"); qemu_log("--------------\n");
log_target_disas(cs, pc_start, dc->pc - pc_start); log_target_disas(cs, pc_start, dc->pc - pc_start);
qemu_log_unlock(); qemu_log_unlock(logfile);
} }
#endif #endif
#endif #endif

View File

@ -892,11 +892,11 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
#ifdef DEBUG_DISAS #ifdef DEBUG_DISAS
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM) if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
&& qemu_log_in_addr_range(tb->pc)) { && qemu_log_in_addr_range(tb->pc)) {
qemu_log_lock(); FILE *logfile = qemu_log_lock();
qemu_log("IN: %s\n", lookup_symbol(tb->pc)); qemu_log("IN: %s\n", lookup_symbol(tb->pc));
log_target_disas(cs, tb->pc, dc->pc - tb->pc); log_target_disas(cs, tb->pc, dc->pc - tb->pc);
qemu_log("\n"); qemu_log("\n");
qemu_log_unlock(); qemu_log_unlock(logfile);
} }
#endif #endif
} }

View File

@ -2388,7 +2388,6 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
dc->zero = NULL; dc->zero = NULL;
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) { if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
qemu_log_lock();
qemu_log("IN: %s\n", lookup_symbol(pc_start)); qemu_log("IN: %s\n", lookup_symbol(pc_start));
} }
gen_tb_start(tb); gen_tb_start(tb);
@ -2417,11 +2416,6 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
gen_tb_end(tb, num_insns); gen_tb_end(tb, num_insns);
tb->size = dc->pc - pc_start; tb->size = dc->pc - pc_start;
tb->icount = num_insns; tb->icount = num_insns;
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
qemu_log("\n");
qemu_log_unlock();
}
} }
void restore_state_to_opc(CPUTLGState *env, TranslationBlock *tb, void restore_state_to_opc(CPUTLGState *env, TranslationBlock *tb,

View File

@ -1994,12 +1994,12 @@ done_generating:
#ifdef DEBUG_DISAS #ifdef DEBUG_DISAS
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM) if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
&& qemu_log_in_addr_range(pc_start)) { && qemu_log_in_addr_range(pc_start)) {
qemu_log_lock(); FILE *logfile = qemu_log_lock();
qemu_log("----------------\n"); qemu_log("----------------\n");
qemu_log("IN: %s\n", lookup_symbol(pc_start)); qemu_log("IN: %s\n", lookup_symbol(pc_start));
log_target_disas(cs, pc_start, dc->pc - pc_start); log_target_disas(cs, pc_start, dc->pc - pc_start);
qemu_log("\n"); qemu_log("\n");
qemu_log_unlock(); qemu_log_unlock(logfile);
} }
#endif #endif
tb->size = dc->pc - pc_start; tb->size = dc->pc - pc_start;

View File

@ -1085,7 +1085,7 @@ void tcg_prologue_init(TCGContext *s)
#ifdef DEBUG_DISAS #ifdef DEBUG_DISAS
if (qemu_loglevel_mask(CPU_LOG_TB_OUT_ASM)) { if (qemu_loglevel_mask(CPU_LOG_TB_OUT_ASM)) {
qemu_log_lock(); FILE *logfile = qemu_log_lock();
qemu_log("PROLOGUE: [size=%zu]\n", prologue_size); qemu_log("PROLOGUE: [size=%zu]\n", prologue_size);
if (s->data_gen_ptr) { if (s->data_gen_ptr) {
size_t code_size = s->data_gen_ptr - buf0; size_t code_size = s->data_gen_ptr - buf0;
@ -1110,7 +1110,7 @@ void tcg_prologue_init(TCGContext *s)
} }
qemu_log("\n"); qemu_log("\n");
qemu_log_flush(); qemu_log_flush();
qemu_log_unlock(); qemu_log_unlock(logfile);
} }
#endif #endif
@ -2114,9 +2114,17 @@ static void tcg_dump_ops(TCGContext *s, bool have_prefs)
} }
if (have_prefs || op->life) { if (have_prefs || op->life) {
for (; col < 40; ++col) {
putc(' ', qemu_logfile); QemuLogFile *logfile;
rcu_read_lock();
logfile = atomic_rcu_read(&qemu_logfile);
if (logfile) {
for (; col < 40; ++col) {
putc(' ', logfile->fd);
}
} }
rcu_read_unlock();
} }
if (op->life) { if (op->life) {
@ -4041,11 +4049,11 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb)
#ifdef DEBUG_DISAS #ifdef DEBUG_DISAS
if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP) if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP)
&& qemu_log_in_addr_range(tb->pc))) { && qemu_log_in_addr_range(tb->pc))) {
qemu_log_lock(); FILE *logfile = qemu_log_lock();
qemu_log("OP:\n"); qemu_log("OP:\n");
tcg_dump_ops(s, false); tcg_dump_ops(s, false);
qemu_log("\n"); qemu_log("\n");
qemu_log_unlock(); qemu_log_unlock(logfile);
} }
#endif #endif
@ -4086,11 +4094,11 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb)
#ifdef DEBUG_DISAS #ifdef DEBUG_DISAS
if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP_IND) if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP_IND)
&& qemu_log_in_addr_range(tb->pc))) { && qemu_log_in_addr_range(tb->pc))) {
qemu_log_lock(); FILE *logfile = qemu_log_lock();
qemu_log("OP before indirect lowering:\n"); qemu_log("OP before indirect lowering:\n");
tcg_dump_ops(s, false); tcg_dump_ops(s, false);
qemu_log("\n"); qemu_log("\n");
qemu_log_unlock(); qemu_log_unlock(logfile);
} }
#endif #endif
/* Replace indirect temps with direct temps. */ /* Replace indirect temps with direct temps. */
@ -4107,11 +4115,11 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb)
#ifdef DEBUG_DISAS #ifdef DEBUG_DISAS
if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP_OPT) if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP_OPT)
&& qemu_log_in_addr_range(tb->pc))) { && qemu_log_in_addr_range(tb->pc))) {
qemu_log_lock(); FILE *logfile = qemu_log_lock();
qemu_log("OP after optimization and liveness analysis:\n"); qemu_log("OP after optimization and liveness analysis:\n");
tcg_dump_ops(s, true); tcg_dump_ops(s, true);
qemu_log("\n"); qemu_log("\n");
qemu_log_unlock(); qemu_log_unlock(logfile);
} }
#endif #endif

View File

@ -53,12 +53,7 @@ check_qemu()
INVOCATION="$@" INVOCATION="$@"
fi fi
if command -v gtester > /dev/null 2>&1 && \ make $MAKEFLAGS $INVOCATION
gtester --version > /dev/null 2>&1; then
make $MAKEFLAGS $INVOCATION
else
echo "No working gtester, skipping make $INVOCATION"
fi
} }
test_fail() test_fail()

View File

@ -34,8 +34,13 @@ static char *create_test_img(int secs)
fd = mkstemp(template); fd = mkstemp(template);
g_assert(fd >= 0); g_assert(fd >= 0);
ret = ftruncate(fd, (off_t)secs * 512); ret = ftruncate(fd, (off_t)secs * 512);
g_assert(ret == 0);
close(fd); close(fd);
if (ret) {
free(template);
template = NULL;
}
return template; return template;
} }
@ -934,6 +939,10 @@ int main(int argc, char **argv)
for (i = 0; i < backend_last; i++) { for (i = 0; i < backend_last; i++) {
if (img_secs[i] >= 0) { if (img_secs[i] >= 0) {
img_file_name[i] = create_test_img(img_secs[i]); img_file_name[i] = create_test_img(img_secs[i]);
if (!img_file_name[i]) {
g_test_message("Could not create test images.");
goto test_add_done;
}
} else { } else {
img_file_name[i] = NULL; img_file_name[i] = NULL;
} }
@ -965,6 +974,7 @@ int main(int argc, char **argv)
"skipping hd-geo/override/* tests"); "skipping hd-geo/override/* tests");
} }
test_add_done:
ret = g_test_run(); ret = g_test_run();
for (i = 0; i < backend_last; i++) { for (i = 0; i < backend_last; i++) {

View File

@ -59,10 +59,7 @@ fi
# Sanity check: For raw, we require a file system that permits the creation # Sanity check: For raw, we require a file system that permits the creation
# of a HUGE (but very sparse) file. Check we can create it before continuing. # of a HUGE (but very sparse) file. Check we can create it before continuing.
if [ "$IMGFMT" = "raw" ]; then if [ "$IMGFMT" = "raw" ]; then
if ! truncate --size=5T "$TEST_IMG"; then _require_large_file 5T
_notrun "file system on $TEST_DIR does not support large enough files"
fi
rm "$TEST_IMG"
fi fi
echo echo

View File

@ -49,6 +49,9 @@ _supported_fmt qcow2
_supported_proto file _supported_proto file
_supported_os Linux _supported_os Linux
# The repair process will create a large file - so check for availability first
_require_large_file 64G
rt_offset=65536 # 0x10000 (XXX: just an assumption) rt_offset=65536 # 0x10000 (XXX: just an assumption)
rb_offset=131072 # 0x20000 (XXX: just an assumption) rb_offset=131072 # 0x20000 (XXX: just an assumption)
l1_offset=196608 # 0x30000 (XXX: just an assumption) l1_offset=196608 # 0x30000 (XXX: just an assumption)

View File

@ -39,6 +39,9 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
_supported_fmt qcow2 _supported_fmt qcow2
_supported_proto file nfs _supported_proto file nfs
# Some containers (e.g. non-x86 on Travis) do not allow large files
_require_large_file 4G
echo "=== Check option preallocation and cluster_size ===" echo "=== Check option preallocation and cluster_size ==="
echo echo
cluster_sizes="16384 32768 65536 131072 262144 524288 1048576 2097152 4194304" cluster_sizes="16384 32768 65536 131072 262144 524288 1048576 2097152 4194304"

View File

@ -42,10 +42,8 @@ echo "== Creating huge file =="
# Sanity check: We require a file system that permits the creation # Sanity check: We require a file system that permits the creation
# of a HUGE (but very sparse) file. tmpfs works, ext4 does not. # of a HUGE (but very sparse) file. tmpfs works, ext4 does not.
if ! truncate --size=513T "$TEST_IMG"; then _require_large_file 513T
_notrun "file system on $TEST_DIR does not support large enough files"
fi
rm "$TEST_IMG"
IMGOPTS='cluster_size=2M,refcount_bits=1' _make_test_img 513T IMGOPTS='cluster_size=2M,refcount_bits=1' _make_test_img 513T
echo "== Populating refcounts ==" echo "== Populating refcounts =="

View File

@ -643,5 +643,15 @@ _require_drivers()
done done
} }
# Check that we have a file system that allows huge (but very sparse) files
#
_require_large_file()
{
if ! truncate --size="$1" "$TEST_IMG"; then
_notrun "file system on $TEST_DIR does not support large enough files"
fi
rm "$TEST_IMG"
}
# make sure this script returns success # make sure this script returns success
true true

View File

@ -13,6 +13,6 @@ DOCKER_IMAGE:=
ifneq ($(DOCKER_IMAGE),) ifneq ($(DOCKER_IMAGE),)
build-tcg-tests-$(PROBE_TARGET): docker-image-$(DOCKER_IMAGE) build-tcg-tests-$(PROBE_TARGET): docker-image-$(DOCKER_IMAGE)
endif
$(BUILD_DIR)/tests/tcg/config_$(PROBE_TARGET).mak: config-host.mak $(BUILD_DIR)/tests/tcg/config_$(PROBE_TARGET).mak: config-host.mak
config-host.mak: $(SRC_PATH)/tests/tcg/configure.sh config-host.mak: $(SRC_PATH)/tests/tcg/configure.sh
endif

View File

@ -36,8 +36,10 @@ TMPC="${TMPDIR1}/qemu-conf.c"
TMPE="${TMPDIR1}/qemu-conf.exe" TMPE="${TMPDIR1}/qemu-conf.exe"
container="no" container="no"
if has "docker" || has "podman"; then if test $use_containers = "yes"; then
container=$($python $source_path/tests/docker/docker.py probe) if has "docker" || has "podman"; then
container=$($python $source_path/tests/docker/docker.py probe)
fi
fi fi
# cross compilers defaults, can be overridden with --cross-cc-ARCH # cross compilers defaults, can be overridden with --cross-cc-ARCH

View File

@ -108,6 +108,82 @@ static void test_parse_path(gconstpointer data)
error_free_or_abort(&err); error_free_or_abort(&err);
} }
static void test_logfile_write(gconstpointer data)
{
QemuLogFile *logfile;
QemuLogFile *logfile2;
gchar const *dir = data;
Error *err = NULL;
g_autofree gchar *file_path;
g_autofree gchar *file_path1;
FILE *orig_fd;
/*
* Before starting test, set log flags, to ensure the file gets
* opened below with the call to qemu_set_log_filename().
* In cases where a logging backend other than log is used,
* this is needed.
*/
qemu_set_log(CPU_LOG_TB_OUT_ASM);
file_path = g_build_filename(dir, "qemu_test_log_write0.log", NULL);
file_path1 = g_build_filename(dir, "qemu_test_log_write1.log", NULL);
/*
* Test that even if an open file handle is changed,
* our handle remains valid due to RCU.
*/
qemu_set_log_filename(file_path, &err);
g_assert(!err);
rcu_read_lock();
logfile = atomic_rcu_read(&qemu_logfile);
orig_fd = logfile->fd;
g_assert(logfile && logfile->fd);
fprintf(logfile->fd, "%s 1st write to file\n", __func__);
fflush(logfile->fd);
/* Change the logfile and ensure that the handle is still valid. */
qemu_set_log_filename(file_path1, &err);
g_assert(!err);
logfile2 = atomic_rcu_read(&qemu_logfile);
g_assert(logfile->fd == orig_fd);
g_assert(logfile2->fd != logfile->fd);
fprintf(logfile->fd, "%s 2nd write to file\n", __func__);
fflush(logfile->fd);
rcu_read_unlock();
}
static void test_logfile_lock(gconstpointer data)
{
FILE *logfile;
gchar const *dir = data;
Error *err = NULL;
g_autofree gchar *file_path;
file_path = g_build_filename(dir, "qemu_test_logfile_lock0.log", NULL);
/*
* Test the use of the logfile lock, such
* that even if an open file handle is closed,
* our handle remains valid for use due to RCU.
*/
qemu_set_log_filename(file_path, &err);
logfile = qemu_log_lock();
g_assert(logfile);
fprintf(logfile, "%s 1st write to file\n", __func__);
fflush(logfile);
/*
* Initiate a close file and make sure our handle remains
* valid since we still have the logfile lock.
*/
qemu_log_close();
fprintf(logfile, "%s 2nd write to file\n", __func__);
fflush(logfile);
qemu_log_unlock(logfile);
g_assert(!err);
}
/* Remove a directory and all its entries (non-recursive). */ /* Remove a directory and all its entries (non-recursive). */
static void rmdir_full(gchar const *root) static void rmdir_full(gchar const *root)
{ {
@ -134,6 +210,10 @@ int main(int argc, char **argv)
g_test_add_func("/logging/parse_range", test_parse_range); g_test_add_func("/logging/parse_range", test_parse_range);
g_test_add_data_func("/logging/parse_path", tmp_path, test_parse_path); g_test_add_data_func("/logging/parse_path", tmp_path, test_parse_path);
g_test_add_data_func("/logging/logfile_write_path",
tmp_path, test_logfile_write);
g_test_add_data_func("/logging/logfile_lock_path",
tmp_path, test_logfile_lock);
rc = g_test_run(); rc = g_test_run();

View File

@ -406,10 +406,21 @@ test_file_monitor_events(void)
char *pathdst = NULL; char *pathdst = NULL;
QFileMonitorTestData data; QFileMonitorTestData data;
GHashTable *ids = g_hash_table_new(g_int64_hash, g_int64_equal); GHashTable *ids = g_hash_table_new(g_int64_hash, g_int64_equal);
char *travis_arch;
qemu_mutex_init(&data.lock); qemu_mutex_init(&data.lock);
data.records = NULL; data.records = NULL;
/*
* This test does not work on Travis LXD containers since some
* syscalls are blocked in that environment.
*/
travis_arch = getenv("TRAVIS_ARCH");
if (travis_arch && !g_str_equal(travis_arch, "x86_64")) {
g_test_skip("Test does not work on non-x86 Travis containers.");
return;
}
/* /*
* The file monitor needs the main loop running in * The file monitor needs the main loop running in
* order to receive events from inotify. We must * order to receive events from inotify. We must

View File

@ -34,6 +34,7 @@ vm-help vm-test:
@echo " DEBUG=1 - Enable verbose output on host and interactive debugging" @echo " DEBUG=1 - Enable verbose output on host and interactive debugging"
@echo " V=1 - Enable verbose ouput on host and guest commands" @echo " V=1 - Enable verbose ouput on host and guest commands"
@echo " QEMU=/path/to/qemu - Change path to QEMU binary" @echo " QEMU=/path/to/qemu - Change path to QEMU binary"
@echo " QEMU_IMG=/path/to/qemu-img - Change path to qemu-img tool"
vm-build-all: $(addprefix vm-build-, $(IMAGES)) vm-build-all: $(addprefix vm-build-, $(IMAGES))

View File

@ -152,6 +152,11 @@ class BaseVM(object):
def build_image(self, img): def build_image(self, img):
raise NotImplementedError raise NotImplementedError
def exec_qemu_img(self, *args):
cmd = [os.environ.get("QEMU_IMG", "qemu-img")]
cmd.extend(list(args))
subprocess.check_call(cmd)
def add_source_dir(self, src_dir): def add_source_dir(self, src_dir):
name = "data-" + hashlib.sha1(src_dir.encode("utf-8")).hexdigest()[:5] name = "data-" + hashlib.sha1(src_dir.encode("utf-8")).hexdigest()[:5]
tarfile = os.path.join(self._tmpdir, name + ".tar") tarfile = os.path.join(self._tmpdir, name + ".tar")

View File

@ -68,7 +68,7 @@ class CentosVM(basevm.BaseVM):
sys.stderr.write("Extracting the image...\n") sys.stderr.write("Extracting the image...\n")
subprocess.check_call(["ln", "-f", cimg, img_tmp + ".xz"]) subprocess.check_call(["ln", "-f", cimg, img_tmp + ".xz"])
subprocess.check_call(["xz", "--keep", "-dvf", img_tmp + ".xz"]) subprocess.check_call(["xz", "--keep", "-dvf", img_tmp + ".xz"])
subprocess.check_call(["qemu-img", "resize", img_tmp, "50G"]) self.exec_qemu_img("resize", img_tmp, "50G")
self.boot(img_tmp, extra_args = ["-cdrom", self._gen_cloud_init_iso()]) self.boot(img_tmp, extra_args = ["-cdrom", self._gen_cloud_init_iso()])
self.wait_ssh() self.wait_ssh()
self.ssh_root_check("touch /etc/cloud/cloud-init.disabled") self.ssh_root_check("touch /etc/cloud/cloud-init.disabled")

View File

@ -74,9 +74,7 @@ class FedoraVM(basevm.BaseVM):
self.print_step("Preparing iso and disk image") self.print_step("Preparing iso and disk image")
subprocess.check_call(["cp", "-f", cimg, iso]) subprocess.check_call(["cp", "-f", cimg, iso])
subprocess.check_call(["qemu-img", "create", "-f", "qcow2", self.exec_qemu_img("create", "-f", "qcow2", img_tmp, self.size)
img_tmp, self.size])
self.print_step("Booting installer") self.print_step("Booting installer")
self.boot(img_tmp, extra_args = [ self.boot(img_tmp, extra_args = [
"-bios", "pc-bios/bios-256k.bin", "-bios", "pc-bios/bios-256k.bin",

View File

@ -82,8 +82,7 @@ class FreeBSDVM(basevm.BaseVM):
self.print_step("Preparing iso and disk image") self.print_step("Preparing iso and disk image")
subprocess.check_call(["cp", "-f", cimg, iso_xz]) subprocess.check_call(["cp", "-f", cimg, iso_xz])
subprocess.check_call(["xz", "-dvf", iso_xz]) subprocess.check_call(["xz", "-dvf", iso_xz])
subprocess.check_call(["qemu-img", "create", "-f", "qcow2", self.exec_qemu_img("create", "-f", "qcow2", img_tmp, self.size)
img_tmp, self.size])
self.print_step("Booting installer") self.print_step("Booting installer")
self.boot(img_tmp, extra_args = [ self.boot(img_tmp, extra_args = [

View File

@ -77,8 +77,7 @@ class NetBSDVM(basevm.BaseVM):
self.print_step("Preparing iso and disk image") self.print_step("Preparing iso and disk image")
subprocess.check_call(["ln", "-f", cimg, iso]) subprocess.check_call(["ln", "-f", cimg, iso])
subprocess.check_call(["qemu-img", "create", "-f", "qcow2", self.exec_qemu_img("create", "-f", "qcow2", img_tmp, self.size)
img_tmp, self.size])
self.print_step("Booting installer") self.print_step("Booting installer")
self.boot(img_tmp, extra_args = [ self.boot(img_tmp, extra_args = [

View File

@ -73,8 +73,7 @@ class OpenBSDVM(basevm.BaseVM):
self.print_step("Preparing iso and disk image") self.print_step("Preparing iso and disk image")
subprocess.check_call(["cp", "-f", cimg, iso]) subprocess.check_call(["cp", "-f", cimg, iso])
subprocess.check_call(["qemu-img", "create", "-f", "qcow2", self.exec_qemu_img("create", "-f", "qcow2", img_tmp, self.size)
img_tmp, self.size])
self.print_step("Booting installer") self.print_step("Booting installer")
self.boot(img_tmp, extra_args = [ self.boot(img_tmp, extra_args = [

View File

@ -70,7 +70,7 @@ class UbuntuX86VM(basevm.BaseVM):
sha256sum="28969840626d1ea80bb249c08eef1a4533e8904aa51a327b40f37ac4b4ff04ef") sha256sum="28969840626d1ea80bb249c08eef1a4533e8904aa51a327b40f37ac4b4ff04ef")
img_tmp = img + ".tmp" img_tmp = img + ".tmp"
subprocess.check_call(["cp", "-f", cimg, img_tmp]) subprocess.check_call(["cp", "-f", cimg, img_tmp])
subprocess.check_call(["qemu-img", "resize", img_tmp, "50G"]) self.exec_qemu_img("resize", img_tmp, "50G")
self.boot(img_tmp, extra_args = ["-cdrom", self._gen_cloud_init_iso()]) self.boot(img_tmp, extra_args = ["-cdrom", self._gen_cloud_init_iso()])
self.wait_ssh() self.wait_ssh()
self.ssh_root_check("touch /etc/cloud/cloud-init.disabled") self.ssh_root_check("touch /etc/cloud/cloud-init.disabled")

View File

@ -98,38 +98,6 @@ TraceEvent *trace_event_name(const char *name)
return NULL; return NULL;
} }
static bool pattern_glob(const char *pat, const char *ev)
{
while (*pat != '\0' && *ev != '\0') {
if (*pat == *ev) {
pat++;
ev++;
}
else if (*pat == '*') {
if (pattern_glob(pat, ev+1)) {
return true;
} else if (pattern_glob(pat+1, ev)) {
return true;
} else {
return false;
}
} else {
return false;
}
}
while (*pat == '*') {
pat++;
}
if (*pat == '\0' && *ev == '\0') {
return true;
} else {
return false;
}
}
void trace_event_iter_init(TraceEventIter *iter, const char *pattern) void trace_event_iter_init(TraceEventIter *iter, const char *pattern)
{ {
iter->event = 0; iter->event = 0;
@ -148,8 +116,7 @@ TraceEvent *trace_event_iter_next(TraceEventIter *iter)
iter->group++; iter->group++;
} }
if (!iter->pattern || if (!iter->pattern ||
pattern_glob(iter->pattern, g_pattern_match_simple(iter->pattern, trace_event_get_name(ev))) {
trace_event_get_name(ev))) {
return ev; return ev;
} }
} }

View File

@ -24,9 +24,11 @@
#include "qapi/error.h" #include "qapi/error.h"
#include "qemu/cutils.h" #include "qemu/cutils.h"
#include "trace/control.h" #include "trace/control.h"
#include "qemu/thread.h"
static char *logfilename; static char *logfilename;
FILE *qemu_logfile; static QemuMutex qemu_logfile_mutex;
QemuLogFile *qemu_logfile;
int qemu_loglevel; int qemu_loglevel;
static int log_append = 0; static int log_append = 0;
static GArray *debug_regions; static GArray *debug_regions;
@ -35,10 +37,14 @@ static GArray *debug_regions;
int qemu_log(const char *fmt, ...) int qemu_log(const char *fmt, ...)
{ {
int ret = 0; int ret = 0;
if (qemu_logfile) { QemuLogFile *logfile;
rcu_read_lock();
logfile = atomic_rcu_read(&qemu_logfile);
if (logfile) {
va_list ap; va_list ap;
va_start(ap, fmt); va_start(ap, fmt);
ret = vfprintf(qemu_logfile, fmt, ap); ret = vfprintf(logfile->fd, fmt, ap);
va_end(ap); va_end(ap);
/* Don't pass back error results. */ /* Don't pass back error results. */
@ -46,57 +52,91 @@ int qemu_log(const char *fmt, ...)
ret = 0; ret = 0;
} }
} }
rcu_read_unlock();
return ret; return ret;
} }
static void __attribute__((__constructor__)) qemu_logfile_init(void)
{
qemu_mutex_init(&qemu_logfile_mutex);
}
static void qemu_logfile_free(QemuLogFile *logfile)
{
g_assert(logfile);
if (logfile->fd != stderr) {
fclose(logfile->fd);
}
g_free(logfile);
}
static bool log_uses_own_buffers; static bool log_uses_own_buffers;
/* enable or disable low levels log */ /* enable or disable low levels log */
void qemu_set_log(int log_flags) void qemu_set_log(int log_flags)
{ {
bool need_to_open_file = false;
QemuLogFile *logfile;
qemu_loglevel = log_flags; qemu_loglevel = log_flags;
#ifdef CONFIG_TRACE_LOG #ifdef CONFIG_TRACE_LOG
qemu_loglevel |= LOG_TRACE; qemu_loglevel |= LOG_TRACE;
#endif #endif
if (!qemu_logfile && /*
(is_daemonized() ? logfilename != NULL : qemu_loglevel)) { * In all cases we only log if qemu_loglevel is set.
* Also:
* If not daemonized we will always log either to stderr
* or to a file (if there is a logfilename).
* If we are daemonized,
* we will only log if there is a logfilename.
*/
if (qemu_loglevel && (!is_daemonized() || logfilename)) {
need_to_open_file = true;
}
qemu_mutex_lock(&qemu_logfile_mutex);
if (qemu_logfile && !need_to_open_file) {
logfile = qemu_logfile;
atomic_rcu_set(&qemu_logfile, NULL);
call_rcu(logfile, qemu_logfile_free, rcu);
} else if (!qemu_logfile && need_to_open_file) {
logfile = g_new0(QemuLogFile, 1);
if (logfilename) { if (logfilename) {
qemu_logfile = fopen(logfilename, log_append ? "a" : "w"); logfile->fd = fopen(logfilename, log_append ? "a" : "w");
if (!qemu_logfile) { if (!logfile->fd) {
g_free(logfile);
perror(logfilename); perror(logfilename);
_exit(1); _exit(1);
} }
/* In case we are a daemon redirect stderr to logfile */ /* In case we are a daemon redirect stderr to logfile */
if (is_daemonized()) { if (is_daemonized()) {
dup2(fileno(qemu_logfile), STDERR_FILENO); dup2(fileno(logfile->fd), STDERR_FILENO);
fclose(qemu_logfile); fclose(logfile->fd);
/* This will skip closing logfile in qemu_log_close() */ /* This will skip closing logfile in qemu_log_close() */
qemu_logfile = stderr; logfile->fd = stderr;
} }
} else { } else {
/* Default to stderr if no log file specified */ /* Default to stderr if no log file specified */
assert(!is_daemonized()); assert(!is_daemonized());
qemu_logfile = stderr; logfile->fd = stderr;
} }
/* must avoid mmap() usage of glibc by setting a buffer "by hand" */ /* must avoid mmap() usage of glibc by setting a buffer "by hand" */
if (log_uses_own_buffers) { if (log_uses_own_buffers) {
static char logfile_buf[4096]; static char logfile_buf[4096];
setvbuf(qemu_logfile, logfile_buf, _IOLBF, sizeof(logfile_buf)); setvbuf(logfile->fd, logfile_buf, _IOLBF, sizeof(logfile_buf));
} else { } else {
#if defined(_WIN32) #if defined(_WIN32)
/* Win32 doesn't support line-buffering, so use unbuffered output. */ /* Win32 doesn't support line-buffering, so use unbuffered output. */
setvbuf(qemu_logfile, NULL, _IONBF, 0); setvbuf(logfile->fd, NULL, _IONBF, 0);
#else #else
setvbuf(qemu_logfile, NULL, _IOLBF, 0); setvbuf(logfile->fd, NULL, _IOLBF, 0);
#endif #endif
log_append = 1; log_append = 1;
} }
atomic_rcu_set(&qemu_logfile, logfile);
} }
if (qemu_logfile && qemu_mutex_unlock(&qemu_logfile_mutex);
(is_daemonized() ? logfilename == NULL : !qemu_loglevel)) {
qemu_log_close();
}
} }
void qemu_log_needs_buffers(void) void qemu_log_needs_buffers(void)
@ -113,6 +153,7 @@ void qemu_set_log_filename(const char *filename, Error **errp)
{ {
char *pidstr; char *pidstr;
g_free(logfilename); g_free(logfilename);
logfilename = NULL;
pidstr = strstr(filename, "%"); pidstr = strstr(filename, "%");
if (pidstr) { if (pidstr) {
@ -224,18 +265,29 @@ out:
/* fflush() the log file */ /* fflush() the log file */
void qemu_log_flush(void) void qemu_log_flush(void)
{ {
fflush(qemu_logfile); QemuLogFile *logfile;
rcu_read_lock();
logfile = atomic_rcu_read(&qemu_logfile);
if (logfile) {
fflush(logfile->fd);
}
rcu_read_unlock();
} }
/* Close the log file */ /* Close the log file */
void qemu_log_close(void) void qemu_log_close(void)
{ {
if (qemu_logfile) { QemuLogFile *logfile;
if (qemu_logfile != stderr) {
fclose(qemu_logfile); qemu_mutex_lock(&qemu_logfile_mutex);
} logfile = qemu_logfile;
qemu_logfile = NULL;
if (logfile) {
atomic_rcu_set(&qemu_logfile, NULL);
call_rcu(logfile, qemu_logfile_free, rcu);
} }
qemu_mutex_unlock(&qemu_logfile_mutex);
} }
const QEMULogItem qemu_log_items[] = { const QEMULogItem qemu_log_items[] = {