From ed4be5fd894b4184d2487f4049327337375d7695 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ciro=20Santilli=20=E5=85=AD=E5=9B=9B=E4=BA=8B=E4=BB=B6=20?= =?UTF-8?q?=E6=B3=95=E8=BD=AE=E5=8A=9F?= Date: Fri, 21 Feb 2020 00:00:00 +0000 Subject: [PATCH] gem5 syscall: better describe behaviour --- README.adoc | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/README.adoc b/README.adoc index e973133..044cc34 100644 --- a/README.adoc +++ b/README.adoc @@ -10820,15 +10820,17 @@ At 369a47fc6e5c2f4a7f911c1c058b6088f8824463 + 1 QEMU appears to spawn 3 host thr ====== gem5 syscall emulation multithreading -gem5 user mode multithreading has been particularly flaky compared <>. +gem5 user mode multithreading has been particularly flaky compared <>, but work is being put into improving it. -You have the limitation that you must have at least one core per guest thread, otherwise `pthread_create` fails. For example: +In gem5 syscall simulation, the `fork` syscall checks if there is a free CPU, and if there is a free one, the new threads runs on that CPU. Otherwise, the `fork` call, and therefore higher level interfaces to `fork` such as `pthread_create` also fail and return a failure return status in the guest. + +For example, if we use just one CPU for link:userland/posix/pthread_self.c[] which spawns one thread besides `main`: .... ./run --cpus 1 --emulator gem5 --userland userland/posix/pthread_self.c --userland-args 1 .... -fails because that process has a total of 2 threads: one for `main` and one extra thread spawned: link:userland/posix/pthread_self.c[] The error message is: +fails with this error message coming from the guest stderr: .... pthread_create: Resource temporarily unavailable @@ -10840,9 +10842,15 @@ It works however if we add on extra CPU: ./run --cpus 2 --emulator gem5 --userland userland/posix/pthread_self.c --userland-args 1 .... -This has to do with the fact that gem5 has a more simplistic thread implementation that does not spawn one host thread per guest thread CPU. Maybe this is required to achieve reproducible runs? What is the task switch algorithm then? +Once threads exit, their CPU is freed and becomes available for new `fork` calls: For example, the following run spawns a thread, joins it, and then spawns again, and 2 CPUs are enough: -gem5 threading does however show the expected number of cores, e.g.: +.... +./run --cpus 2 --emulator gem5 --userland userland/posix/pthread_self.c --userland-args '1 2' +.... + +because at each point in time, only up to two threads are running. + +gem5 syscall emulation does show the expected number of cores when queried, e.g.: .... ./run --cpus 1 --userland userland/cpp/thread_hardware_concurrency.cpp --emulator gem5 @@ -10851,18 +10859,6 @@ gem5 threading does however show the expected number of cores, e.g.: outputs `1` and `2` respectively. -TODO: aarch64 seems to failing to spawn more than 2 threads at 369a47fc6e5c2f4a7f911c1c058b6088f8824463 + 1: - -.... -./run --arch aarch64 --cpus 3 --emulator gem5 --userland userland/posix/pthread_self.c --userland-args 2 -.... - -fails with: - -.... -Exiting @ tick 18446744073709551615 because simulate() limit reached -.... - ====== gem5 se.py user mode with 2 or more pthreads fails with because simulate() limit reached See bug report at: https://github.com/cirosantilli/linux-kernel-module-cheat/issues/81