]> rtime.felk.cvut.cz Git - frescor/fosa.git/commitdiff
FOSA-PaRTiKle: fixes in long jumps
authorbrocalv <brocalv@35b4ef3e-fd22-0410-ab77-dab3279adceb>
Mon, 19 May 2008 13:24:34 +0000 (13:24 +0000)
committerbrocalv <brocalv@35b4ef3e-fd22-0410-ab77-dab3279adceb>
Mon, 19 May 2008 13:24:34 +0000 (13:24 +0000)
git-svn-id: http://www.frescor.org/private/svn/frescor/fosa/trunk@1177 35b4ef3e-fd22-0410-ab77-dab3279adceb

include/fosa_opaque_types.h
src_partikle/fosa_long_jump.c
src_partikle/fosa_setjmp.S
src_partikle/tests/test_long_jump.c

index bf2ee76cb093b28bb7ef62a8c401837e3d85a795..8f47e5f18a77e772571da9123ae1cdf8c624047f 100644 (file)
@@ -333,6 +333,7 @@ typedef pthread_mutex_t FOSA_MUTEX_T_OPAQUE;
 #include <sched.h>
 #include <stdlib.h>
 #include <setjmp.h>
+#include <limits.h>
 
 typedef struct {
     posix_appsched_actions_t actions;
@@ -343,11 +344,7 @@ typedef struct {
     bool activated;
 } FOSA_ADS_ACTIONS_T_OPAQUE;
 
-typedef struct {
-  jmp_buf jmp_context;
-  bool jmp_hasexecuted;
-  sigset_t jmp_sigmask;
-} FOSA_LONG_JUMP_CONTEXT_T_OPAQUE;
+typedef unsigned long FOSA_LONG_JUMP_CONTEXT_T_OPAQUE [32];
 
 typedef pthread_t                   FOSA_THREAD_ID_T_OPAQUE;
 typedef pthread_attr_t              FOSA_THREAD_ATTR_T_OPAQUE;
@@ -363,13 +360,19 @@ enum _fosa_clocks_e {
   FOSA_SYSTEM_CLOCK_OPAQUE = CLOCK_MONOTONIC
 };
 
+#define LONGJMP_NSIG 3
+
+#if LONGJMP_NSIG > (RTSIG_MAX - 1)
+#   error LONGJMP_NSIG too big (LONGJMP_NSIG > RTSIG_MAX - 1)
+#endif
+
 enum _fosa_signal_limits_e {
-  LONGJMP_NSIG = 3,
   LONGJMP_FIRSTSIG = SIGRTMAX - LONGJMP_NSIG + 1,
   FOSA_SIGNAL_MAX = LONGJMP_FIRSTSIG - 1,
   FOSA_SIGNAL_MIN = FOSA_SIGNAL_MAX,
 };
 
+
 enum _fosa_errors_e {
   FOSA_EINVAL = EINVAL,
   FOSA_EAGAIN = EAGAIN,
index e59a69ff5d4a3dabaf2d03932179370bb749e4dd..0868ec76182ad6fac072f66ab05d3ec241491f9c 100644 (file)
@@ -69,7 +69,7 @@
 #include <stdio.h>
 
 #define LONGJMP_MAGIC 0x01234567
-int jmp_used_signals [LONGJMP_NSIG] = {[0 ... (LONGJMP_NSIG - 1)] = 0};
+pthread_t jmp_used_signals [LONGJMP_NSIG] = {[0 ... (LONGJMP_NSIG - 1)] = NULL};
 pthread_mutex_t signal_pool_m = PTHREAD_MUTEX_INITIALIZER;
 
 extern void fosa_longjmp (fosa_long_jump_context_t ctx, unsigned long magic);
@@ -80,7 +80,6 @@ int fosa_long_jump_was_performed
   if (!context && !jumped)
     return FOSA_EINVAL;
 
-//   printf ("context [6]=%ld\n", (*(context))[6]);
   *jumped = ((*(context))[6] == LONGJMP_MAGIC);
   return 0;
 }
@@ -90,11 +89,14 @@ void jmp_handler (int signo, siginfo_t *info, void *context)
 {
   fosa_long_jump_context_t *jmp_info = (fosa_long_jump_context_t *) info -> si_value.sival_ptr;
 
-#ifdef CONFIG_LONGJUMP_FREE_SIGNAL
-  sigset_t set;
+  sigset_t s;
 
   // Restore the signal mask
-//   pthread_sigmask (SIG_SETMASK, &(jmp_info -> jmp_sigmask), NULL);
+  s.sig = (*jmp_info)[7];
+  pthread_sigmask (SIG_SETMASK, &s, NULL);
+
+#ifdef CONFIG_LONGJUMP_FREE_SIGNAL
+  sigset_t set;
 
   // Free this signal
   sigemptyset (&set);
@@ -102,11 +104,10 @@ void jmp_handler (int signo, siginfo_t *info, void *context)
   pthread_sigmask (SIG_BLOCK, &sigmask, NULL);
 
   pthread_mutex_lock (&signal_pool_m);
-  jmp_used_signals [signo] = 0;
+  jmp_used_signals [signo] = NULL;
   pthread_mutex_unlock (&signal_pool_m);
 #endif
 
-//   printf ("\t\t\t\t>>>  RESTORE CONTEXT  <<<\n\n");
   // Restore the saved context
   fosa_longjmp (*jmp_info, LONGJMP_MAGIC);
   return;
@@ -120,6 +121,15 @@ int fosa_long_jump_install_handler
   struct sigaction sa;
   sigset_t sigmask;
 
+  // Check if current thread has a handler associated
+  for (i = 0; i < LONGJMP_NSIG; i ++)
+    if (jmp_used_signals [i] == pthread_self ()) {
+      sigemptyset (&sigmask);
+      sigaddset (&sigmask, LONGJMP_FIRSTSIG + i);
+      pthread_sigmask (SIG_UNBLOCK, &sigmask, NULL);
+      return 0;
+    }
+
   // Find the first usable signal
   pthread_mutex_lock (&signal_pool_m);
   for (i = 0; i < LONGJMP_NSIG && jmp_used_signals [i]; i++);
@@ -128,7 +138,7 @@ int fosa_long_jump_install_handler
     return FOSA_ENOMEM;
   }
 
-  jmp_used_signals [i] = 1;
+  jmp_used_signals [i] = pthread_self ();
   pthread_mutex_unlock (&signal_pool_m);
 
   *signal = LONGJMP_FIRSTSIG + i;
index 08795cec873fee5b9e63e19d2f56b9c4e8cce002..e72d1277a38ce945dd02fdd581e3b2a8df577e88 100644 (file)
        
 .text
 
-.global fosa_long_jump_save_context, fosa_longjmp
+.global fosa_long_jump_save_context, fosa_setjmp, fosa_longjmp
 .type   fosa_long_jump_save_context,@function
+.type   fosa_setjmp,@function
 .type   fosa_longjmp,@function
 
+
 fosa_long_jump_save_context:
+       subl    $44,  %esp
+       cmpl    $0, 48(%esp)
+       jne     .L2
+       movl    $22, 24(%esp)
+       jmp     .L4
+.L2:
+       movl    44(%esp), %ecx
+       leal    48(%esp), %edx
+       movl    48(%esp), %eax
+       movl    %ebx, 0(%eax)
+       movl    %esi, 4(%eax)
+       movl    %edi, 8(%eax)
+       movl    %ebp, 12(%eax)
+       movl    %edx, 16(%eax)
+       movl    %ecx, 20(%eax)
+       movl    $0,   24(%eax)
+
+        leal    28(%eax), %eax
+        movl    %eax, 8(%esp)
+        movl    $0, 4(%esp)
+        movl    $0, (%esp)
+        call    pthread_sigmask
+
+.L4:
+       movl    24(%esp), %eax
+       addl    $44, %esp
+       ret
+
+
+fosa_setjmp:
        movl 0(%esp), %ecx
        leal 4(%esp), %edx
        movl (%edx), %eax
index e4bba651f1f8620b09b63d928d4e4b9269f63e52..b9b12d440644c161d8007070ea76d7adf0f70613 100644 (file)
@@ -10,38 +10,57 @@ void f1 (void)
        fosa_thread_id_t th;
        int jmp;
        fosa_signal_info_t ctx_info;
+       sigset_t s;
        
+       pthread_sigmask (SIG_SETMASK, NULL, &s);
+       printf (">>> Current signal mask = 0x%x\n", (unsigned int) s.sig);
        
        printf (">>> save context\n\n");
-       if (fosa_long_jump_save_context (&ctx))
-               perror ("fosa_long_jump_save_context");
+       if (fosa_long_jump_save_context (&ctx)) {
+               printf ("fosa_long_jump_save_context");
+               exit (-1);
+       }
        
        printf (">>> check jump performed\n\n");
-       if (fosa_long_jump_was_performed ((const fosa_long_jump_context_t *) &ctx, &jmp))
-               perror ("fosa_long_jump_was_performed");
+       if (fosa_long_jump_was_performed ((const fosa_long_jump_context_t *) &ctx, &jmp)) {
+               printf ("fosa_long_jump_was_performed");
+               exit (-2);
+       }
        
        if (jmp) {
                printf ("\t <<<< JUMPED\n\n");
+               pthread_sigmask (SIG_SETMASK, NULL, &s);
+               printf (">>> Current signal mask = 0x%x\n",(unsigned int) s.sig);
                exit (10);
        }
-
+       
        printf (">>> install handler\n\n");
-       if (fosa_long_jump_install_handler (&sig, &th))
-               perror ("fosa_long_jump_install_handler()");
-               
+       if (fosa_long_jump_install_handler (&sig, &th)) {
+               printf ("fosa_long_jump_install_handler()");
+               exit (-3);
+       }
+       
        printf ("\t signal=%d, thread=0x%x (self=0x%x)\n",  sig, (unsigned int) th, (unsigned int) fosa_thread_self());
        
        printf (">>> trigger a long jump using a signal\n\n");
        ctx_info.sival_ptr = &ctx;
-       if (fosa_signal_queue (sig, ctx_info, th))
-               perror ("fosa_signal_queue");
-       
+       if (fosa_signal_queue (sig, ctx_info, th)) {
+               printf ("fosa_signal_queue");
+               exit (-4);
+       }
 }
 
 
 int main (void)
 {
-       f1 ();
-       return 0;
+  sigset_t s;
+
+  sigemptyset (&s);
+  sigaddset (&s, SIGRTMIN);
+  sigaddset (&s, SIGRTMAX);
+  pthread_sigmask (SIG_SETMASK, &s, NULL);
+
+  f1 ();
+  return 0;
 }