From: Jeremy Fitzhardinge Date: Wed, 17 Mar 2004 18:20:46 +0000 (+0000) Subject: Add susphello test, which has turned up a number of interesting bugs X-Git-Tag: svn/VALGRIND_2_1_2~172 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3ee834af04963258de4d140c685badd312cf0c48;p=thirdparty%2Fvalgrind.git Add susphello test, which has turned up a number of interesting bugs git-svn-id: svn://svn.valgrind.org/valgrind/trunk@2333 --- diff --git a/none/tests/Makefile.am b/none/tests/Makefile.am index a9a7840ffe..e8715e02b2 100644 --- a/none/tests/Makefile.am +++ b/none/tests/Makefile.am @@ -45,6 +45,7 @@ EXTRA_DIST = $(noinst_SCRIPTS) \ resolv.stderr.exp resolv.stdout.exp resolv.vgtest \ seg_override.stderr.exp \ seg_override.stdout.exp seg_override.vgtest \ + susphello.stdout.exp susphello.stderr.exp susphello.vgtest \ sha1_test.stderr.exp sha1_test.vgtest \ shortpush.stderr.exp shortpush.vgtest \ shorts.stderr.exp shorts.vgtest \ @@ -61,7 +62,7 @@ check_PROGRAMS = \ fucomip $(INSN_TESTS) \ int munmap_exe map_unmap mremap rcl_assert \ rcrl readline1 resolv seg_override sha1_test shortpush shorts smc1 \ - pth_blockedsig pushpopseg \ + susphello pth_blockedsig pushpopseg \ syscall-restart1 syscall-restart2 system \ coolo_sigaction gxx304 yield @@ -111,6 +112,8 @@ smc1_SOURCES = smc1.c sha1_test_SOURCES = sha1_test.c shortpush_SOURCES = shortpush.c shorts_SOURCES = shorts.c +susphello_SOURCES = susphello.c +susphello_LDADD = -lpthread syscall_restart1_SOURCES = syscall-restart1.c syscall_restart2_SOURCES = syscall-restart2.c system_SOURCES = system.c diff --git a/none/tests/susphello.c b/none/tests/susphello.c new file mode 100644 index 0000000000..179dd947ee --- /dev/null +++ b/none/tests/susphello.c @@ -0,0 +1,305 @@ +/* JSGF: no idea what this is actually doing, but it really gives the + signals/sigaltstack/threads machinery a working out */ +/** + * Compile with: + * gcc -g -Wall -lpthread -o susphello susphello.c + * + * Author Magnus Ihse, ihse at bea.com + */ + +#include + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include +#include +#include +#include +#include +#include + +#define THREAD_COUNT 10 +#define ITER_COUNT 200 + +static volatile int finishedArray[THREAD_COUNT]; +static int pKey; + +static sigset_t srSigset; + +pthread_t main_thread; + +int srSignal = SIGUSR1; + + +void +ptiSrSigHandler(int sig, siginfo_t *sip, void *arg) +{ + //ucontext_t *ucontext = (ucontext_t *)arg; + + int mypos = (int) pthread_getspecific(pKey); + + +// int threadPos = (int)pthread_getspecific(srThreadKey); + +// thread->os_context = (OSContextP)&(ucontext->uc_mcontext); + + // Notify suspender that we have been suspended + if (pthread_kill(main_thread, srSignal) == -1) { + perror("pthread_kill"); + exit(1); + } + + finishedArray[mypos]++; + +// printf("this is thread %d: i'm now suspended!\n", mypos); + + // Wait until we are resumed + while (sigwaitinfo(&srSigset, NULL) == -1) { + // Interrupted by SIGSTOP in gdb + if(errno != EINTR) { + perror("sigwaitinfo"); + exit(1); + } + } + +// printf("this is thread %d: i'm now resumed!\n", mypos); + + //thread->os_context = NULL; // just for the sake of it... + + // Notify resumer that we have been resumed + if (pthread_kill(main_thread, srSignal) == -1) { + perror("pthread_kill"); + exit(1); + } +// printf("this is thread %d: and I've told Master!!\n", mypos); + +} + + +void +suspendOrResume(pthread_t thread, int i) +{ + sigset_t oss; + + // Mask out suspend/resume signal until we explicitly wait for it + sigprocmask(SIG_BLOCK, &srSigset, &oss); + + // Send signal to suspend or resume the thread + if (pthread_kill(thread, srSignal) == -1) { + perror("pthread_kill"); + exit(1); + } + +// printf("sent signal to %d...", i); + // Wait for notification from thread being suspended/resumed + while (sigwaitinfo(&srSigset, NULL) == -1) { + // Interrupted by SIGSTOP in gdb + if(errno != EINTR) { + perror("sigwaitinfo"); + exit(1); + } + } + + // Restore original signal mask + sigprocmask(SIG_SETMASK, &oss, NULL); + +// printf("... okay, %d suspended\n", i); +} + + + +void +initSignalling(void) +{ + struct sigaction sa; + + // Signal mask for suspend/resume + sigemptyset(&srSigset); + sigaddset(&srSigset, srSignal); + + // Set up signal handler for suspend/resume + sa.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK; + sa.sa_sigaction = ptiSrSigHandler; + sigfillset(&sa.sa_mask); + sigdelset(&sa.sa_mask, (__SIGRTMIN+1)); + if (sigaction(srSignal, &sa, 0) == -1) { + perror("sigaction"); + exit(1); + } + + // Unblock suspend signal + sigprocmask(SIG_UNBLOCK, &srSigset, 0); + + main_thread = pthread_self(); +} + + +void* setup_altstack(void) { + stack_t ss; + + ss.ss_sp = malloc(20*1024); + if (ss.ss_sp == 0) { + return NULL; + } + ss.ss_size = 20*1024; + ss.ss_flags = 0; + + if (sigaltstack(&ss, NULL) == -1) { + perror("sigaltstack"); + return NULL; + } + return ss.ss_sp; +} + +void takedown_altstack(void* stack) { + struct sigaltstack ss; + int result; + + ss.ss_flags = SS_DISABLE; + ss.ss_sp = (void*)47; // This value should be ignored when ss_flags is SS_DISABLE + ss.ss_size = 29; // This value should be ignored when ss_flags is SS_DISABLE + + { + result = sigaltstack(&ss, NULL); + free(stack); + } +} + +void *threadfunc(void *arg) { + int mypos = (int)arg; + int i; + long square = 1; + void* altstack = setup_altstack(); + + pthread_setspecific(pKey, arg); + for (i=0; i < 1000; i++) { + square = i*i + square*mypos; + } + +// wait for signal + while (finishedArray[mypos] == 0) { + struct timespec req, rem; + + req.tv_sec = 0; + req.tv_nsec = 5 * 1000 * 1000; + + nanosleep(&req, &rem); + + }; + + finishedArray[mypos]++; + + takedown_altstack(altstack); + + return NULL; +} + + +int main(int argc, char ** argv) { + pthread_t threads[THREAD_COUNT]; + pthread_attr_t attr; + int result; + int i; + int iteration; + int finished; + + initSignalling(); + + pthread_attr_init(&attr); + pthread_attr_setstacksize(&attr, 128*1024); + + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + + pthread_key_create(&pKey, NULL); + + for (iteration = 0; iteration < ITER_COUNT; iteration++) { +#if 0 + if ((iteration % 100) == 0) { + printf("\nStarting run series %i: ", iteration); + } + + if ((iteration % 10) == 0) { + printf("."); + fflush(stdout); + } +#endif + + // Clear array + for (i = 0; i< THREAD_COUNT; i++) { + finishedArray[i] = 0; + } + + // Start threads + for (i = 0; i< THREAD_COUNT; i++) { + result = pthread_create(&threads[i], &attr, threadfunc, (void*)i); + if (result != 0) { + perror("pthread_create"); + exit(1); + } + } + +// printf("all threads started\n"); + // suspend threads + for (i = 0; i< THREAD_COUNT; i++) { + suspendOrResume(threads[i], i); + } + +// printf("now all threads are suspended\n"); + + // resume threads + for (i = 0; i< THREAD_COUNT; i++) { + suspendOrResume(threads[i], i); + } + + + // Join threads +/* + printf("about to join..."); + for (i = 0; i< THREAD_COUNT; i++) { + result = pthread_join(threads[i], NULL); + if (result != 0) { + perror("pthread_join"); + exit(1); + } + } + + printf("...joined"); +*/ +// printf("Spin waiting for results\n"); + finished = 1; + do { + struct timespec req, rem; + + req.tv_sec = 0; + req.tv_nsec = 5 * 1000 * 1000; + finished = 1; + + nanosleep(&req, &rem); + +// sleep(1); + for (i = 0; i< THREAD_COUNT; i++) { + if (finishedArray[i] < 2) { + finished = 0; +// printf("no result at: %d, value: %d\n", i, finishedArray[i]); + break; + } + } +// sleep(1); + } while (!finished); + + } + + printf("PASSED\n"); + return 0; +} diff --git a/none/tests/susphello.stderr.exp b/none/tests/susphello.stderr.exp new file mode 100644 index 0000000000..139597f9cb --- /dev/null +++ b/none/tests/susphello.stderr.exp @@ -0,0 +1,2 @@ + + diff --git a/none/tests/susphello.stdout.exp b/none/tests/susphello.stdout.exp new file mode 100644 index 0000000000..53cdf1e939 --- /dev/null +++ b/none/tests/susphello.stdout.exp @@ -0,0 +1 @@ +PASSED diff --git a/none/tests/susphello.vgtest b/none/tests/susphello.vgtest new file mode 100644 index 0000000000..0a163ac5b4 --- /dev/null +++ b/none/tests/susphello.vgtest @@ -0,0 +1 @@ +prog: susphello