]> rtime.felk.cvut.cz Git - frescor/fosa.git/blob - src_partikle/fosa_long_jump.c
Fixing license header
[frescor/fosa.git] / src_partikle / fosa_long_jump.c
1 // -----------------------------------------------------------------------
2 //  Copyright (C) 2006 - 2008 FRESCOR consortium partners:
3 //
4 //    Universidad de Cantabria,              SPAIN
5 //    University of York,                    UK
6 //    Scuola Superiore Sant'Anna,            ITALY
7 //    Kaiserslautern University,             GERMANY
8 //    Univ. Politécnica  Valencia,           SPAIN
9 //    Czech Technical University in Prague,  CZECH REPUBLIC
10 //    ENEA                                   SWEDEN
11 //    Thales Communication S.A.              FRANCE
12 //    Visual Tools S.A.                      SPAIN
13 //    Rapita Systems Ltd                     UK
14 //    Evidence                               ITALY
15 //
16 //    See http://www.frescor.org for a link to partners' websites
17 //
18 //           FRESCOR project (FP6/2005/IST/5-034026) is funded
19 //        in part by the European Union Sixth Framework Programme
20 //        The European Union is not liable of any use that may be
21 //        made of this code.
22 //
23 //
24 //  based on previous work (FSF) done in the FIRST project
25 //
26 //   Copyright (C) 2005  Mälardalen University, SWEDEN
27 //                       Scuola Superiore S.Anna, ITALY
28 //                       Universidad de Cantabria, SPAIN
29 //                       University of York, UK
30 //
31 //   FSF API web pages: http://marte.unican.es/fsf/docs
32 //                      http://shark.sssup.it/contrib/first/docs/
33 //
34 //   This file is part of FOSA (Frsh Operating System Adaption)
35 //
36 //  FOSA is free software; you can redistribute it and/or modify it
37 //  under terms of the GNU General Public License as published by the
38 //  Free Software Foundation; either version 2, or (at your option) any
39 //  later version.  FOSA is distributed in the hope that it will be
40 //  useful, but WITHOUT ANY WARRANTY; without even the implied warranty
41 //  of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
42 //  General Public License for more details. You should have received a
43 //  copy of the GNU General Public License along with FOSA; see file
44 //  COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,
45 //  Cambridge, MA 02139, USA.
46 //
47 //  As a special exception, including FOSA header files in a file,
48 //  instantiating FOSA generics or templates, or linking other files
49 //  with FOSA objects to produce an executable application, does not
50 //  by itself cause the resulting executable application to be covered
51 //  by the GNU General Public License. This exception does not
52 //  however invalidate any other reasons why the executable file might be
53 //  covered by the GNU Public License.
54 // -----------------------------------------------------------------------
55 //fosa_long_jump.c
56 //==============================================
57 //  ********  ******    ********  **********
58 //  **///// /**    **  **//////  /**     /**
59 //  **      /**    ** /**        /**     /**
60 //  ******* /**    ** /********* /**********
61 //  **////  /**    ** ////////** /**//////**
62 //  **      /**    **        /** /**     /**
63 //  **      /**    **  ********  /**     /**
64 //  //       /******/  ////////   //      //
65 //
66 // FOSA(Frescor Operating System Adaptation layer)
67 //================================================
68
69 #ifdef CONFIG_LONGJUMP
70
71 #include <fosa_long_jump.h>
72 #include <stdio.h>
73
74 #define LONGJMP_MAGIC 0x01234567
75 pthread_t jmp_used_signals [LONGJMP_NSIG] = {[0 ... (LONGJMP_NSIG - 1)] = NULL};
76 pthread_mutex_t signal_pool_m = PTHREAD_MUTEX_INITIALIZER;
77
78 extern void fosa_longjmp (fosa_long_jump_context_t ctx, unsigned long magic);
79
80 int fosa_long_jump_was_performed
81     (const fosa_long_jump_context_t * context, int * jumped)
82 {
83   if (!context && !jumped)
84     return FOSA_EINVAL;
85
86   *jumped = ((*(context))[6] == LONGJMP_MAGIC);
87   return 0;
88 }
89
90
91 void jmp_handler (int signo, siginfo_t *info, void *context)
92 {
93   fosa_long_jump_context_t *jmp_info = (fosa_long_jump_context_t *) info -> si_value.sival_ptr;
94
95   sigset_t s;
96
97   // Restore the signal mask
98   s.sig = (*jmp_info)[7];
99   pthread_sigmask (SIG_SETMASK, &s, NULL);
100
101 #ifdef CONFIG_LONGJUMP_FREE_SIGNAL
102   sigset_t set;
103
104   // Free this signal
105   sigemptyset (&set);
106   sigaddset (&set, signo);
107   pthread_sigmask (SIG_BLOCK, &sigmask, NULL);
108
109   pthread_mutex_lock (&signal_pool_m);
110   jmp_used_signals [signo] = NULL;
111   pthread_mutex_unlock (&signal_pool_m);
112 #endif
113
114   // Restore the saved context
115   fosa_longjmp (*jmp_info, LONGJMP_MAGIC);
116   return;
117 }
118
119
120 int fosa_long_jump_install_handler
121     (fosa_signal_t *signal, fosa_thread_id_t *handler)
122 {
123   int i;
124   struct sigaction sa;
125   sigset_t sigmask;
126
127   // Check if current thread has a handler associated
128   for (i = 0; i < LONGJMP_NSIG; i ++)
129     if (jmp_used_signals [i] == pthread_self ()) {
130       sigemptyset (&sigmask);
131       sigaddset (&sigmask, LONGJMP_FIRSTSIG + i);
132       pthread_sigmask (SIG_UNBLOCK, &sigmask, NULL);
133       return 0;
134     }
135
136   // Find the first usable signal
137   pthread_mutex_lock (&signal_pool_m);
138   for (i = 0; i < LONGJMP_NSIG && jmp_used_signals [i]; i++);
139   if (i >= LONGJMP_NSIG) {
140     pthread_mutex_unlock (&signal_pool_m);
141     return FOSA_ENOMEM;
142   }
143
144   jmp_used_signals [i] = pthread_self ();
145   pthread_mutex_unlock (&signal_pool_m);
146
147   *signal = LONGJMP_FIRSTSIG + i;
148   *handler = pthread_self ();
149
150   // intall the jump handler
151   sa.sa_flags = SA_SIGINFO;
152   sigfillset (&sa.sa_mask);
153   sa.sa_sigaction = jmp_handler;
154   sigaction (*signal, &sa, NULL);
155
156   // unmask the signal for the calling thread
157   sigemptyset (&sigmask);
158   sigaddset (&sigmask, *signal);
159   pthread_sigmask (SIG_UNBLOCK, &sigmask, NULL);
160
161   return 0;
162 }
163
164 #endif /* CONFIG_LONGJUMP */