From: Bart Van Assche Date: Mon, 15 Feb 2021 02:42:04 +0000 (-0800) Subject: drd/tests/swapcontext: Add a swapcontext() test X-Git-Tag: VALGRIND_3_17_0~53 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0062f2b519ea48b82164ae423fac58a59ee00f1a;p=thirdparty%2Fvalgrind.git drd/tests/swapcontext: Add a swapcontext() test --- diff --git a/drd/tests/Makefile.am b/drd/tests/Makefile.am index 5df76150e9..a489c8b46d 100644 --- a/drd/tests/Makefile.am +++ b/drd/tests/Makefile.am @@ -267,6 +267,8 @@ EXTRA_DIST = \ sem_open_traced.vgtest \ sem_wait.stderr.exp \ sem_wait.vgtest \ + swapcontext.stderr.exp \ + swapcontext.vgtest \ sigalrm.stderr.exp \ sigalrm.vgtest \ sigaltstack.stderr.exp \ @@ -406,6 +408,7 @@ check_PROGRAMS = \ sem_as_mutex \ sem_open \ sigalrm \ + swapcontext \ threaded-fork \ trylock \ unit_bitmap \ @@ -585,3 +588,5 @@ std_thread2_LDFLAGS = -Wl,--no-as-needed endif sem_wait_SOURCES = sem_wait.cpp + +swapcontext_SOURCES = swapcontext.c diff --git a/drd/tests/swapcontext.c b/drd/tests/swapcontext.c new file mode 100644 index 0000000000..e73a612dc3 --- /dev/null +++ b/drd/tests/swapcontext.c @@ -0,0 +1,124 @@ +/* See also https://bugs.kde.org/show_bug.cgi?id=432381. */ + +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef struct thread_local { + ucontext_t uc[3]; + size_t nrsw; + int tfd; +} thread_local_t; + +static void f(void *data, int n) +{ + enum { NR_SWITCHES = 200000 }; + struct pollfd pfd; + thread_local_t *tlocal = data; + + while (1) { + memset(&pfd, 0, sizeof(pfd)); + pfd.fd = tlocal->tfd; + pfd.events = POLLIN; + + if (poll(&pfd, 1, 0) == 1) { + if (++tlocal->nrsw == NR_SWITCHES) + return; + swapcontext(&tlocal->uc[n], &tlocal->uc[3 - n]); + } + } +} + +void __valgrind_register_current_stack(void) +{ + pthread_attr_t attr; + size_t stacksize; + void *stack; + + if (pthread_getattr_np(pthread_self(), &attr) != 0) + abort(); + + if (pthread_attr_getstack(&attr, &stack, &stacksize) != 0) + abort(); + + VALGRIND_STACK_REGISTER(stack, stack + stacksize); +} + +#define STACKSIZE 8192 + +void *worker(void *data) +{ + thread_local_t *tlocal = data; + struct itimerspec it; + + __valgrind_register_current_stack(); + + tlocal->tfd = timerfd_create(CLOCK_REALTIME, 0); + if (tlocal->tfd < 0) + abort(); + + it.it_interval.tv_sec = 0; + it.it_interval.tv_nsec = 1000; + + it.it_value.tv_sec = time(NULL); + it.it_value.tv_nsec = 1000; + + if (timerfd_settime(tlocal->tfd, TFD_TIMER_ABSTIME, &it, NULL) < 0) + abort(); + + if (getcontext(&(tlocal->uc[1])) < 0) + abort(); + if (getcontext(&(tlocal->uc[2])) < 0) + abort(); + + tlocal->uc[1].uc_link = &tlocal->uc[0]; + tlocal->uc[1].uc_stack.ss_sp = malloc(STACKSIZE); + tlocal->uc[1].uc_stack.ss_size = STACKSIZE; + makecontext(&tlocal->uc[1], (void (*)(void))f, 2, tlocal, 1); + VALGRIND_STACK_REGISTER(tlocal->uc[1].uc_stack.ss_sp, + tlocal->uc[1].uc_stack.ss_sp + + tlocal->uc[1].uc_stack.ss_size); + + tlocal->uc[2].uc_link = &tlocal->uc[0]; + tlocal->uc[2].uc_stack.ss_sp = malloc(STACKSIZE); + tlocal->uc[2].uc_stack.ss_size = STACKSIZE; + makecontext(&tlocal->uc[2], (void (*)(void))f, 2, tlocal, 2); + VALGRIND_STACK_REGISTER(tlocal->uc[2].uc_stack.ss_sp, + tlocal->uc[2].uc_stack.ss_sp + + tlocal->uc[2].uc_stack.ss_size); + + swapcontext(&tlocal->uc[0], &tlocal->uc[1]); + return NULL; +} + +int main(int argc, char *argv[]) +{ + enum { NR = 32 }; + thread_local_t tlocal[NR]; + pthread_t thread[NR]; + int i; + + memset(tlocal, 0, sizeof(tlocal)); + + for (i = 0; i < NR; i++) + pthread_create(&thread[i], NULL, worker, &tlocal[i]); + + // Wait until the threads have been created. + sleep(1); + for (i = 0; i < NR; i++) + pthread_kill(thread[i], SIGINT); + + for (i = 0; i < NR; i++) + pthread_join(thread[i], NULL); + + return 0; +} diff --git a/drd/tests/swapcontext.stderr.exp b/drd/tests/swapcontext.stderr.exp new file mode 100644 index 0000000000..1ebc73a407 --- /dev/null +++ b/drd/tests/swapcontext.stderr.exp @@ -0,0 +1,7 @@ + + +Process terminating with default action of signal 2 (SIGINT) + at 0x........: swapcontext (in /...libc...) + by 0x........: f (swapcontext.c:?) + +ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0) diff --git a/drd/tests/swapcontext.vgtest b/drd/tests/swapcontext.vgtest new file mode 100644 index 0000000000..98e3712c40 --- /dev/null +++ b/drd/tests/swapcontext.vgtest @@ -0,0 +1,4 @@ +prereq: test -e swapcontext && ./supported_libpthread +vgopts: --read-var-info=yes --check-stack-var=yes --show-confl-seg=no --num-callers=2 +prog: swapcontext +stderr_filter: filter_stderr