#include <sched.h>
#include <stdlib.h>
#include <setjmp.h>
+#include <limits.h>
typedef struct {
posix_appsched_actions_t actions;
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;
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,
#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);
if (!context && !jumped)
return FOSA_EINVAL;
-// printf ("context [6]=%ld\n", (*(context))[6]);
*jumped = ((*(context))[6] == LONGJMP_MAGIC);
return 0;
}
{
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);
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;
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++);
return FOSA_ENOMEM;
}
- jmp_used_signals [i] = 1;
+ jmp_used_signals [i] = pthread_self ();
pthread_mutex_unlock (&signal_pool_m);
*signal = LONGJMP_FIRSTSIG + i;
.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
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;
}