]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Add susphello test, which has turned up a number of interesting bugs
authorJeremy Fitzhardinge <jeremy@valgrind.org>
Wed, 17 Mar 2004 18:20:46 +0000 (18:20 +0000)
committerJeremy Fitzhardinge <jeremy@valgrind.org>
Wed, 17 Mar 2004 18:20:46 +0000 (18:20 +0000)
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@2333

none/tests/Makefile.am
none/tests/susphello.c [new file with mode: 0644]
none/tests/susphello.stderr.exp [new file with mode: 0644]
none/tests/susphello.stdout.exp [new file with mode: 0644]
none/tests/susphello.vgtest [new file with mode: 0644]

index a9a7840ffe8ddd16c5d92d00116798e589889073..e8715e02b2f200c6266ff838ebd4a0be1e30e833 100644 (file)
@@ -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 (file)
index 0000000..179dd94
--- /dev/null
@@ -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 <signal.h>
+
+
+#include <errno.h>
+#include <stddef.h>
+#include <pthread.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/resource.h>
+#include <unistd.h>
+#include <sys/syscall.h>
+#include <dlfcn.h>
+
+
+#include <pthread.h>
+#include <unistd.h>
+#include <string.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#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 (file)
index 0000000..139597f
--- /dev/null
@@ -0,0 +1,2 @@
+
+
diff --git a/none/tests/susphello.stdout.exp b/none/tests/susphello.stdout.exp
new file mode 100644 (file)
index 0000000..53cdf1e
--- /dev/null
@@ -0,0 +1 @@
+PASSED
diff --git a/none/tests/susphello.vgtest b/none/tests/susphello.vgtest
new file mode 100644 (file)
index 0000000..0a163ac
--- /dev/null
@@ -0,0 +1 @@
+prog: susphello