diff options
| author | Peter Maydell <peter.maydell@linaro.org> | 2021-06-07 15:45:48 +0100 |
|---|---|---|
| committer | Peter Maydell <peter.maydell@linaro.org> | 2021-06-07 15:45:48 +0100 |
| commit | a35947f15c0ee695eba3c55248ec8ac3e4e23cca (patch) | |
| tree | 8349ec065369e5007353a96d8ea6223697127336 /tests/tcg/multiarch/signals.c | |
| parent | 6f398e533f5e259b4f937f4aa9de970f7201d166 (diff) | |
| parent | 72205289a0799c6d0a73107198098b830dbea2f9 (diff) | |
| download | focaccia-qemu-a35947f15c0ee695eba3c55248ec8ac3e4e23cca.tar.gz focaccia-qemu-a35947f15c0ee695eba3c55248ec8ac3e4e23cca.zip | |
Merge remote-tracking branch 'remotes/stsquad/tags/pull-testing-updates-070621-2' into staging
A few testing and configure updates: - add the multiarch signals stress test - fix display of multi-word compiler stanzas in meson - fix quoting of multi-word compiler stazas in configure.sh - tag some acceptance tests as TCG only - make checkpatch test work harder to find clean diffs - split gprof/gconv job to avoid timeouts - fix centos8 VM build by adding --source-path - make checkpatch aware of .h.inc and .c.inc paths # gpg: Signature made Mon 07 Jun 2021 14:51:12 BST # 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-testing-updates-070621-2: scripts/checkpatch.pl: process .c.inc and .h.inc files as C source tests/vm: expose --source-path to scripts to find extra files gitlab-ci: Split gprof-gcov job gitlab: work harder to avoid false positives in checkpatch tests/acceptance: tag various arm tests as TCG only tests/tcg/configure.sh: tweak quoting of target_compiler meson.build: fix cosmetics of compiler display tests/tcg: add a multiarch signals test to stress test signal delivery Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'tests/tcg/multiarch/signals.c')
| -rw-r--r-- | tests/tcg/multiarch/signals.c | 149 |
1 files changed, 149 insertions, 0 deletions
diff --git a/tests/tcg/multiarch/signals.c b/tests/tcg/multiarch/signals.c new file mode 100644 index 0000000000..998c8fdefd --- /dev/null +++ b/tests/tcg/multiarch/signals.c @@ -0,0 +1,149 @@ +/* + * linux-user signal handling tests. + * + * Copyright (c) 2021 Linaro Ltd + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include <stdarg.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <errno.h> +#include <pthread.h> +#include <string.h> +#include <signal.h> +#include <time.h> +#include <sys/time.h> + +static void error1(const char *filename, int line, const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + fprintf(stderr, "%s:%d: ", filename, line); + vfprintf(stderr, fmt, ap); + fprintf(stderr, "\n"); + va_end(ap); + exit(1); +} + +static int __chk_error(const char *filename, int line, int ret) +{ + if (ret < 0) { + error1(filename, line, "%m (ret=%d, errno=%d/%s)", + ret, errno, strerror(errno)); + } + return ret; +} + +#define error(fmt, ...) error1(__FILE__, __LINE__, fmt, ## __VA_ARGS__) + +#define chk_error(ret) __chk_error(__FILE__, __LINE__, (ret)) + +/* + * Thread handling + */ +typedef struct ThreadJob ThreadJob; + +struct ThreadJob { + int number; + int sleep; + int count; +}; + +static pthread_t *threads; +static int max_threads = 10; +__thread int signal_count; +int total_signal_count; + +static void *background_thread_func(void *arg) +{ + ThreadJob *job = (ThreadJob *) arg; + + printf("thread%d: started\n", job->number); + while (total_signal_count < job->count) { + usleep(job->sleep); + } + printf("thread%d: saw %d alarms from %d\n", job->number, + signal_count, total_signal_count); + return NULL; +} + +static void spawn_threads(void) +{ + int i; + threads = calloc(sizeof(pthread_t), max_threads); + + for (i = 0; i < max_threads; i++) { + ThreadJob *job = calloc(sizeof(ThreadJob), 1); + job->number = i; + job->sleep = i * 1000; + job->count = i * 100; + pthread_create(threads + i, NULL, background_thread_func, job); + } +} + +static void close_threads(void) +{ + int i; + for (i = 0; i < max_threads; i++) { + pthread_join(threads[i], NULL); + } + free(threads); + threads = NULL; +} + +static void sig_alarm(int sig, siginfo_t *info, void *puc) +{ + if (sig != SIGRTMIN) { + error("unexpected signal"); + } + signal_count++; + __atomic_fetch_add(&total_signal_count, 1, __ATOMIC_SEQ_CST); +} + +static void test_signals(void) +{ + struct sigaction act; + struct itimerspec it; + timer_t tid; + struct sigevent sev; + + /* Set up SIG handler */ + act.sa_sigaction = sig_alarm; + sigemptyset(&act.sa_mask); + act.sa_flags = SA_SIGINFO; + chk_error(sigaction(SIGRTMIN, &act, NULL)); + + /* Create POSIX timer */ + sev.sigev_notify = SIGEV_SIGNAL; + sev.sigev_signo = SIGRTMIN; + sev.sigev_value.sival_ptr = &tid; + chk_error(timer_create(CLOCK_REALTIME, &sev, &tid)); + + it.it_interval.tv_sec = 0; + it.it_interval.tv_nsec = 1000000; + it.it_value.tv_sec = 0; + it.it_value.tv_nsec = 1000000; + chk_error(timer_settime(tid, 0, &it, NULL)); + + spawn_threads(); + + do { + usleep(1000); + } while (total_signal_count < 2000); + + printf("shutting down after: %d signals\n", total_signal_count); + + close_threads(); + + chk_error(timer_delete(tid)); +} + +int main(int argc, char **argv) +{ + test_signals(); + return 0; +} |