]> rtime.felk.cvut.cz Git - frescor/fosa.git/commitdiff
Modifications in FOSA and FOSA-marte for longjumps
authortelleriam <telleriam@35b4ef3e-fd22-0410-ab77-dab3279adceb>
Thu, 15 Nov 2007 16:29:33 +0000 (16:29 +0000)
committertelleriam <telleriam@35b4ef3e-fd22-0410-ab77-dab3279adceb>
Thu, 15 Nov 2007 16:29:33 +0000 (16:29 +0000)
git-svn-id: http://www.frescor.org/private/svn/frescor/fosa/trunk@852 35b4ef3e-fd22-0410-ab77-dab3279adceb

17 files changed:
include/fosa_clocks_and_timers.h
include/fosa_configuration_parameters.h
include/fosa_long_jump.h [new file with mode: 0644]
include/fosa_opaque_types.h
include/fosa_types.h
marte_non_local_jump/Makefile [new file with mode: 0644]
marte_non_local_jump/context.adb [new file with mode: 0644]
marte_non_local_jump/context.ads [new file with mode: 0644]
marte_non_local_jump/eat_20.c [new file with mode: 0644]
marte_non_local_jump/eat_20.h [new file with mode: 0644]
marte_non_local_jump/execute_context.h [new file with mode: 0644]
marte_non_local_jump/marte_non_local_jmp.h [new file with mode: 0644]
marte_non_local_jump/non_local_jump.adb [new file with mode: 0644]
marte_non_local_jump/non_local_jump.ads [new file with mode: 0644]
marte_non_local_jump/non_local_jump_test.adb [new file with mode: 0644]
src_marte/fosa_clocks_and_timers.c
src_marte/fosa_long_jump.c [new file with mode: 0644]

index 2b50dc508bdc7d5437d011747c032528724b8a21..eab2614f5575ae1d3ee5e944b8a0442c1c4b5d6e 100644 (file)
@@ -165,6 +165,28 @@ int fosa_thread_get_cputime_clock(frsh_thread_id_t tid, fosa_clock_id_t *clockid
       (fosa_clock_id_t clockid, frsh_signal_t signal, frsh_signal_info_t info,
        fosa_timer_id_t *timerid);
 
+/**
+ * fosa_timer_create_with_receiver()
+ *
+ * Create a one-shot timer with a specific signal receiver thread
+ *
+ * This function creates a timer in the same way as fosa_timer_create,
+ * except that the signal generated when the timer expires is sent to
+ * the thread specified by receiver
+ *
+ * Returns 0 if successful; otherwise it returns an error code:
+ *     FOSA_EINVAL: the value of clockid or signal is invalid
+ *
+ *     FOSA_EAGAIN: the system lacks enough resources to create the timer
+ *
+ * Alternatively, in case of error the implementation is allowed to
+ * notify it to the system console and then terminate the FRSH
+ * implementation and dependant applications
+ **/
+ int fosa_timer_create_with_receiver
+      (fosa_clock_id_t clockid, frsh_signal_t signal, frsh_signal_info_t info,
+       fosa_timer_id_t *timerid, frsh_thread_id_t receiver);
+
 /**
  * fosa_timer_delete()
  *
index ebad99ddd4c4655d2f3c95ef6fea29b68767c7bf..e2a288c84d29f87ca292465b3299c285487f8c83 100644 (file)
 // with each thread, in the thread-specific data
 #define  FOSA_MAX_KEYS         4
 
+/**
+ * Real-time signal number reserved for the long jump handler
+ **/
+#define FOSA_LONG_JUMP_SIGNAL             FRSH_SIGNAL_MIN+1
+
+
 
 /*********
  *  ADS
diff --git a/include/fosa_long_jump.h b/include/fosa_long_jump.h
new file mode 100644 (file)
index 0000000..c536521
--- /dev/null
@@ -0,0 +1,209 @@
+//----------------------------------------------------------------------
+//  Copyright (C) 2006 - 2007 by the FRESCOR consortium:
+//
+//    Universidad de Cantabria,              SPAIN
+//    University of York,                    UK
+//    Scuola Superiore Sant'Anna,            ITALY
+//    Kaiserslautern University,             GERMANY
+//    Univ. Politecnica  Valencia,           SPAIN
+//    Czech Technical University in Prague,  CZECH REPUBLIC
+//    ENEA                                   SWEDEN
+//    Thales Communication S.A.              FRANCE
+//    Visual Tools S.A.                      SPAIN
+//    Rapita Systems Ltd                     UK
+//    Evidence                               ITALY
+//
+//    See http://www.frescor.org
+//
+//        The FRESCOR project (FP6/2005/IST/5-034026) is funded
+//        in part by the European Union Sixth Framework Programme
+//        The European Union is not liable of any use that may be
+//        made of this code.
+//
+//
+//  based on previous work (FSF) done in the FIRST project
+//
+//   Copyright (C) 2005  Mälardalen University, SWEDEN
+//                       Scuola Superiore S.Anna, ITALY
+//                       Universidad de Cantabria, SPAIN
+//                       University of York, UK
+//
+// This file is part of FOSA (Frsh Operating System Abstraction)
+//
+// FOSA is free software; you can redistribute it and/or modify it
+// under terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option) any
+// later version.  FOSA is distributed in the hope that it will be
+// useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details. You should have received a
+// copy of the GNU General Public License along with FOSA; see file
+// COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,
+// Cambridge, MA 02139, USA.
+//
+// As a special exception, including FOSA header files in a file,
+// instantiating FOSA generics or templates, or linking other files
+// with FOSA objects to produce an executable application, does not
+// by itself cause the resulting executable application to be covered
+// by the GNU General Public License. This exception does not
+// however invalidate any other reasons why the executable file might be
+// covered by the GNU Public License.
+// -----------------------------------------------------------------------
+//fosa_long_jump.h
+//==============================================
+//  ********  ******    ********  **********
+//  **///// /**    **  **//////  /**     /**
+//  **      /**    ** /**        /**     /**
+//  ******* /**    ** /********* /**********
+//  **////  /**    ** ////////** /**//////**
+//  **      /**    **        /** /**     /**
+//  **      /**    **  ********  /**     /**
+//  //       /******/  ////////   //      //
+//
+// FOSA(Frescor Operating System Adaptation layer)
+//================================================
+
+
+#ifndef        FOSA_LONG_JUMP
+#define        FOSA_LONG_JUMP
+
+#include "fosa_types.h"
+#include "fosa_opaque_types.h"
+
+/**
+ * @defgroup longjumps Long Jumps
+ * @ingroup fosa
+ *
+ * This module defines the types and functions that allow te
+ * application to abort a piece of running code; it can be used to
+ * stop an action that is overrunning its budget and needs to be
+ * aborted, without aborting the whole thread on which it is based.
+ *
+ * The model is that the application installs a long-jump handler for
+ * each thread that potentially needs to be aborted through the long
+ * jump mechanism. As a result of installing the handler it gets back
+ * a signal identifier. This signal is later used to notify the
+ * handler that the thread needs to be aborted. Previous to sending
+ * the signal, the application must store the context of the thread so
+ * that when it is aborted the saved context can be recovered. The
+ * signal may be sent to the handler from any thread, but must contain
+ * as attached information a pointer to the variable where the context
+ * was saved.
+ *
+ * The implementation may internally choose to implement a single long
+ * jump handler for all threads (and use a single signal), or one for each
+ * thread (requiring the reservation of a pool of signals).
+ *
+ * @{
+ **/
+
+
+
+/*************************
+ * Functions
+ *************************/
+
+/**
+ *  fosa_long_jump_save_context
+ *
+ *  Save the context of the current thread for a future long jump
+ *
+ *  This function stores in context the information required to modify
+ *  the stack of the calling thread so that a later long jump may be 
+ *  executed in the future to restore this context
+ *
+ *  This function stores in 'context' the thread id, the registers,
+ *  and the stack frame of the calling thread. This information can be
+ *  used by the long jump handler to change the stack of the task so
+ *  that when it is scheduled again it returns to the end of this
+ *  function
+ *
+ *
+ *  Returns 0 if successful; otherwise it returns an error code:
+ *     FOSA_EINVAL: the value of context is invalid
+ *
+ *  Alternatively, in case of error the implementation is allowed to
+ *  notify it to the system console and then terminate the FRSH
+ *  implementation and dependant applications
+ */
+int fosa_long_jump_save_context
+   (fosa_long_jump_context_t * context);
+
+
+/**
+ *  fosa_long_jump_was_performed
+ *
+ *  Check whether the current thread suffered a long jump or not
+ *
+ *  This function should be invoked after fosa_long_jump_save_context
+ *  to determine whether the current thread is executing normally, or
+ *  has suffered a long jump to the point where the context was
+ *  saved. If invoked after a direct invocation to
+ *  fosa_long_jump_save_context, the function shall set the variable
+ *  pointed to by jumped to zero. If invoked after returning from
+ *  fosa_long_jump_save_context due to a call to
+ *  fosa_long_jump_restore_context, the function shall set this
+ *  variable to 1.
+ *
+ *  Returns 0 if successful; otherwise it returns an error code:
+ *     FOSA_EINVAL: the value of context is invalid
+ *
+ *  Alternatively, in case of error the implementation is allowed to
+ *  notify it to the system console and then terminate the FRSH
+ *  implementation and dependant applications
+ */
+int fosa_long_jump_was_performed
+   (const fosa_long_jump_context_t * context, int * jumped);
+
+
+/**
+ *  fosa_long_jump_install_handler
+ *
+ *  Install a long jump handler for the calling thread
+ *
+ *  This function shall install a handler that is capable of causing a
+ *  long jump operation that restores the context of a thread to a
+ *  previously saved value. If the handler has already been installed
+ *  for this thread the previously installed handler will be used and
+ *  the call shall succeed.
+ *
+ *  The long-jump handler is waiting for a signal to notify that a
+ *  thread context should be restored. This signal must carry attached
+ *  to it a pointer to the variable where the thread context was
+ *  saved. The thread referenced in that context will have its
+ *  internal context restored to the point where it was saved. For
+ *  this restore operation to work properly, the program frame where
+ *  the thread saved its context must still be valid.
+ *
+ *  Depending on the implementation a given thread may also install a signal
+ *  handler or a signal handler thread that is capable of executing
+ *  the actions required to restore the context of a thread from the
+ *  appropriate context. For instance, in POSIX it is necesaray that
+ *  the context is restored from the same thread being restored,
+ *  usually from a signal handler of that thread.
+ *
+ *  The function shall store in the variable pointed to by signal the
+ *  identifier of the signal that must be used to notify the request
+ *  for a long jump to be executed. In the variable pointed to by
+ *  handler, it shall store the thread id to which the signal must be
+ *  sent. The signal must be sent with its attached information set to
+ *  a pointer to the variable of type fosa_long_jump_context_t where
+ *  the context of the thread to be restored was saved.
+ *
+ *  Returns 0 if successful; otherwise it returns an error code:
+ *     FOSA_EINVAL: the value of context is invalid
+ *     FOSA_ENOMEM: there are no resources to satisfy the call at this time
+ *
+ *  Alternatively, in case of error the implementation is allowed to
+ *  notify it to the system console and then terminate the FRSH
+ *  implementation and dependant applications
+ */
+int fosa_long_jump_install_handler
+(frsh_signal_t *signal, frsh_thread_id_t *handler);
+
+
+
+/*@}*/
+
+
+#endif             /* !FOSA_LONG_JUMP */
index b8d3998db3297b85885c263269f0eec2eb682883..8f9d3ffecb349728b87bbe9b085b431424b913eb 100644 (file)
@@ -81,7 +81,7 @@
 
 #ifdef RT_LINUX
 #include <rtl_timer.h>
-#endif
+#endif // RT_LINUX
 
 #define    FOSA_CLOCK_ID_T_OPAQUE    clockid_t
 #define    FOSA_SYSTEM_CLOCK_OPAQUE  CLOCK_MONOTONIC
@@ -106,19 +106,33 @@ typedef struct {
 
 
 #define FOSA_ADS_ACTIONS_T_OPAQUE fosa_ads_actions_internal_t
-#else
+
+
+///////////////////
+// Long jumps
+///////////////////
+
+#include "marte_non_local_jmp.h"
+
+#define FOSA_LONG_JUMP_CONTEXT_T_OPAQUE  struct { \
+  marte_nonlocaljmp_context_t marte_context;      \
+  frsh_thread_id_t tid;                            \
+}
+
+#else // MARTE_OS
 
 /* hack to get AQuoSA sources compile without having none
  * of the application level scheduler header files and symbols */
 #ifdef AQuoSA
 #define posix_appsched_actions_t int
-#endif
+#endif // AQuoSA
 
 #define FOSA_ADS_ACTIONS_T_OPAQUE posix_appsched_actions_t
-#endif
+#endif // MARTE_OS
+
 
 
-#endif
+#endif //  defined(RT_LINUX) || defined(MARTE_OS) || defined(AQuoSA)
 
 ////////////////// END OF RT_LINUX, MARTE_OS and AQuoSA //////////////////////
 
@@ -138,6 +152,7 @@ typedef struct {
 
 #define    FOSA_COND_T_OPAQUE        int
 
+
 /*********
  *  ADS
  *********/
index 0b86a56fd34800b3ad33337606546fd5d61abd7b..7140b5862275e8b41f602528899246868bd64f8f 100644 (file)
@@ -346,4 +346,19 @@ typedef struct {
 
 /*@}*/
 
+/*********************
+ *   LONG JUMPS
+ *********************/
+
+/**
+ * The fosa_jump_context_t type defines a data area where the context
+ * of a thread can be saved, so that a long jump to recover that context
+ * may be executed in the future, from a long jump handler.
+ */
+
+typedef     FOSA_LONG_JUMP_CONTEXT_T_OPAQUE    fosa_long_jump_context_t; 
+
+
+
+
 #endif // _FOSA_TYPES_H_
diff --git a/marte_non_local_jump/Makefile b/marte_non_local_jump/Makefile
new file mode 100644 (file)
index 0000000..5f4b930
--- /dev/null
@@ -0,0 +1,10 @@
+all:  non_local_jump_test.exe
+
+non_local_jump_test.exe:  non_local_jump_test.adb non_local_jump.adb non_local_jump.ads eat_20.c eat_20.h
+       mgcc -c -g eat_20.c
+       mgnatmake -o $@ $<
+
+
+clean:
+       rm -f *.o *.exe *.ali b~* mprogram*
+
diff --git a/marte_non_local_jump/context.adb b/marte_non_local_jump/context.adb
new file mode 100644 (file)
index 0000000..d0379f6
--- /dev/null
@@ -0,0 +1,39 @@
+with Text_IO; use Text_IO;\r
+with Basic_Integer_Types;\r
+with Non_Local_Jump;\r
+with System;\r
+\r
+use type Basic_Integer_Types.Unsigned_32;\r
+\r
+package body Context is\r
+\r
+   Jmp_Buff : aliased Non_Local_Jump.Jmp_Context;\r
+   pragma Volatile (Jmp_Buff);\r
+\r
+   TCB : System.Address := System.Null_Address;\r
+   pragma Volatile (TCB);\r
+\r
+   function Pthread_Self return System.Address;\r
+   pragma Import (C, Pthread_Self, "pthread_self");\r
+\r
+   function Execute_Work(Work : Work_Acc) return Integer is\r
+   begin\r
+      Put_Line ("Start work");\r
+      TCB := Pthread_Self;\r
+      Non_Local_Jump.Save_Context(Jmp_Buff'Access);\r
+      if Non_Local_Jump.After_Jump (Jmp_Buff'Access) = 0 then\r
+         Put_Line ("---Not After Jump---");\r
+         Work.all;\r
+         return 0;\r
+      else\r
+         Put_Line ("---After Jump---");\r
+         return 1;\r
+      end if;\r
+   end Execute_Work;\r
+\r
+   procedure Restore_Work is\r
+   begin\r
+      Non_Local_Jump.Restore_Context (TCB, Jmp_Buff'Access);\r
+   end Restore_Work;\r
+\r
+end Context;\r
diff --git a/marte_non_local_jump/context.ads b/marte_non_local_jump/context.ads
new file mode 100644 (file)
index 0000000..707f805
--- /dev/null
@@ -0,0 +1,12 @@
+package Context is\r
+\r
+   type Work_Acc is access procedure;\r
+   pragma Convention (C, Work_Acc);\r
+\r
+   function Execute_Work(Work : Work_Acc) return Integer;\r
+   pragma export(C,Execute_Work, "execute_work");\r
+\r
+   procedure Restore_Work;\r
+   pragma export(C,Restore_Work, "restore_work");\r
+\r
+end Context;\r
diff --git a/marte_non_local_jump/eat_20.c b/marte_non_local_jump/eat_20.c
new file mode 100644 (file)
index 0000000..6180e3b
--- /dev/null
@@ -0,0 +1,7 @@
+void eat_20() {
+  int i;
+  for (i=0; i<200000000; i++){
+    i++;
+    i--;
+  }
+}
diff --git a/marte_non_local_jump/eat_20.h b/marte_non_local_jump/eat_20.h
new file mode 100644 (file)
index 0000000..35cb614
--- /dev/null
@@ -0,0 +1 @@
+void eat_20();
diff --git a/marte_non_local_jump/execute_context.h b/marte_non_local_jump/execute_context.h
new file mode 100644 (file)
index 0000000..0948010
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef _EXECUTE_WORK\r
+#define _EXECUTE_WORK\r
+\r
+\r
+int execute_work (void (*func)());\r
+\r
+void restore_work();\r
+\r
+#endif // _EXECUTE_WORK\r
diff --git a/marte_non_local_jump/marte_non_local_jmp.h b/marte_non_local_jump/marte_non_local_jmp.h
new file mode 100644 (file)
index 0000000..9a70fdb
--- /dev/null
@@ -0,0 +1,103 @@
+/*----------------------------------------------------------------------------\r
+ *------------------------      M a R T E   O S      -------------------------\r
+ *----------------------------------------------------------------------------\r
+ *                                                             {MARTE_VERSION}\r
+ *\r
+ *                   'm a r t e _ n o n _ l o c a l _ j m p'\r
+ *\r
+ *                                    H\r
+ *\r
+ * File 'marte_non_local_jmp.h'                                       By MAR.\r
+ *\r
+ * Non-local jumps for preempted tasks.\r
+ * Functionality implemented in 'non_local_jump.ad[ab]'.\r
+ *\r
+ * {MARTE_COPYRIGHT}\r
+ *\r
+ *---------------------------------------------------------------------------*/\r
+/* {<MAR}\r
+ *\r
+ * 02-08-07: primera versión\r
+ *\r
+ * {MAR>} -------------------------------------------------------------------*/\r
+\r
+#ifndef _MARTE_NON_LOCAL_JMP_H_\r
+#define _MARTE_NON_LOCAL_JMP_H_\r
+\r
+//#include <sys/cpp_macros.h>\r
+#include <sys/types.h>\r
+\r
+//CPP_BEGIN_DECLS\r
+\r
+// GNAT 2005: typedef struct { int b[108/4]; } marte_nonlocaljmp_context_t;\r
+\r
+typedef struct { int b[156/4]; } marte_nonlocaljmp_context_t;\r
+\r
+/*-----------------------------------\r
+ *-- marte_nonlocaljmp_savecontext --\r
+ *-----------------------------------*/\r
+/*\r
+ *  Context stores the information required to modify the stack of a\r
+ *  preempted task with 'restorecontext'.\r
+ *\r
+ *  This function stores in 'context' the registers and its stack frame. This\r
+ *  information can be used for 'restorecontext' to change the stack of the\r
+ *  task (when it is preempted) so that when it is scheduled again it returns\r
+ *  to the end of this function\r
+ */\r
+void marte_nonlocaljmp_savecontext\r
+   (marte_nonlocaljmp_context_t * context);\r
+\r
+/*----------------------------------\r
+ *--  marte_nonlocaljmp_afterjmp  --\r
+ *----------------------------------*/\r
+/*\r
+ * To be invoked after 'Save_Context'. If invoked after a direct invocation\r
+ * to 'Save_Context', 'After_Jump' shall return 0. If invoked after\r
+ * returning from 'Save_Context' due to a call to 'Restore_Context',\r
+ * 'After_Jump' shall return 1.\r
+ */\r
+ int marte_nonlocaljmp_afterjmp(const marte_nonlocaljmp_context_t * context);\r
+\r
+/*--------------------------------------\r
+ *-- marte_nonlocaljmp_restorecontext --\r
+ *--------------------------------------*/\r
+/*\r
+ *  This procedure changes the return context of a preempted task.\r
+ *\r
+ *                    |        |               |       |\r
+ *  TCB_Ac.Stack_Ptr->|  Regs  |               |       |\r
+ *                    |        |               |       |\r
+ *                       ...                      ...\r
+ *                    |        |               |  ret  |<-TCB_Ac.Stack_Ptr\r
+ *                    |        |               |  ebp  |\r
+ *                    |        |<-Context.Esp->|  SC*  |\r
+ *                    |        |               |  SC*  |\r
+ *                    |        |               |  SC*  |\r
+ *                    |        |               |       |\r
+ *                      before                   after\r
+ *  SC*: stack frame of 'Save_Context'.\r
+ *\r
+ *  The next time the task is scheduled will execute the final part of\r
+ *  Save_Context.\r
+ *\r
+ *  The full process is the following: 'Save_Context' stores the registers\r
+ *  and its stack frame in 'Jmp_Context'. 'Restore_Context' restores that\r
+ *  context placing the stored frame in the same position of the stack it was\r
+ *  originally. Over this frame it is placed the value of the ebp register\r
+ *  and the address of label "1:" in 'Save_Context'.\r
+ *  When the task is scheduled again, the first instruction it executes is\r
+ *  "ret" in 'Processor_Registers.Context_Switch' and then the address of\r
+ *  label "1:" in 'Save_Context' is popped from the stack. Once in\r
+ *  'Save_Context', the ebp register is also popped and, with this\r
+ *  instruction, the registers and stack are in the same situation it was the\r
+ *  time that the contexts was stored, and then the final part of\r
+ *  'Save_Context' can be executed successfully.\r
+ */\r
+void marte_nonlocaljmp_restorecontext\r
+  (pthread_t th,\r
+   marte_nonlocaljmp_context_t * context);\r
+\r
+//CPP_END_DECLS\r
+\r
+#endif // _MARTE_NON_LOCAL_JMP_H_\r
diff --git a/marte_non_local_jump/non_local_jump.adb b/marte_non_local_jump/non_local_jump.adb
new file mode 100644 (file)
index 0000000..8741992
--- /dev/null
@@ -0,0 +1,168 @@
+------------------------------------------------------------------------------
+--  ------------------         M a R T E   O S         -------------------  --
+------------------------------------------------------------------------------
+--                                                             {MARTE_VERSION}
+--
+--                      'N o n _ L o c a l _ J u m p'
+--
+--                                  Body
+--
+--  File 'non_local_jump.adb'                                          By MAR
+--
+--  Non-local jumps for preempted tasks.
+--
+--  IMPORTANT: it must be compiled without any optimization!!
+--
+--  {MARTE_COPYRIGHT}
+--
+------------------------------------------------------------------------------
+--  {<MAR}
+--
+--  02-08-07:version operativa.
+--
+--  {MAR>} -------------------------------------------------------------------
+with System.Machine_Code; use System.Machine_Code;
+with Ada.Unchecked_Conversion;
+
+package body Non_Local_Jump is
+   use Basic_Integer_Types;
+   use System;
+
+   pragma Optimize (Off);
+
+   -------------------
+   -- Save_Context --
+   -------------------
+   --
+   --  Context stores the information required to modify the stack of a
+   --  preempted task with 'Change_Return_Context_Of_Preempted_Task'.
+   --
+   --
+   procedure Save_Context (Context : access Jmp_Context) is
+      pragma Optimize (Off);
+
+      function To_Save_Context_Stack_Ac is
+        new Ada.Unchecked_Conversion (Unsigned_32, Save_Context_Stack_Ac);
+   begin
+      --  Store registers
+      Asm ("pushl %%eax;" &
+           "pushl %%ebp;" &
+           "pushl %%edi;" &
+           "pushl %%esi;" &
+           "pushl %%edx;" &
+           "pushl %%ecx;" &
+           "pushl %%ebx;"  &
+           "pushl $1f;",
+           No_Output_Operands, No_Input_Operands, "", True);
+
+      Asm ("popl %0 ;" &
+        "popl %1 ;" &
+        "popl %2 ;" &
+        "popl %3 ;" &
+        "popl %4 ;" &
+        "popl %5 ;" &
+        "popl %6 ;" &
+        "popl %7 ;",
+        (Address'Asm_Output ("=g", Context.Return_Address),
+         Unsigned_32'Asm_Output ("=g", Context.Ebx),
+         Unsigned_32'Asm_Output ("=g", Context.Ecx),
+         Unsigned_32'Asm_Output ("=g", Context.Edx),
+         Unsigned_32'Asm_Output ("=g", Context.Esi),
+         Unsigned_32'Asm_Output ("=g", Context.Edi),
+         Unsigned_32'Asm_Output ("=g", Context.Ebp),
+         Unsigned_32'Asm_Output ("=g", Context.Eax)),
+        No_Input_Operands, "", True);
+
+      --  Mark context has been used in a direct invocation of 'Save_Context'
+      pragma Validity_Checks (Off);
+      Context.After_Jmp := 0;
+      pragma Validity_Checks (On);
+
+      --  Store esp
+      Asm ("movl %%esp, %0;",
+           Unsigned_32'Asm_Output ("=g", Context.Esp),
+           No_Input_Operands, "", True);
+
+      --  Save stack
+      pragma Validity_Checks (Off);
+      Context.Context_Stack := To_Save_Context_Stack_Ac (Context.Esp).all;
+      pragma Validity_Checks (On);
+
+      --  Push ebp to be restored after label "1:"
+      Asm ("pushl %%ebp;",
+           No_Output_Operands, No_Input_Operands, "", True);
+
+      --  return address where the task returns after it is scheduled again. It
+      --  jumps here from the 'ret' instruction in
+      --  'Processor_Registers.Context_Switch'.
+      Asm ("1: popl %%ebp;",
+           No_Output_Operands,
+           No_Input_Operands, "", True);
+   end Save_Context;
+
+   ------------------
+   --  After_Jump  --
+   ------------------
+   --
+   --  To be invoked after 'Save_Context'. If invoked after a direct invocation
+   --  to 'Save_Context', 'After_Jump' shall return False. If invoked after
+   --  returning from 'Save_Context' due to a call to 'Restore_Context',
+   --  'After_Jump' shall return True.
+   function After_Jump (Context : access Jmp_Context) return Unsigned_32 is
+   begin
+      return Context.After_Jmp;
+   end After_Jump;
+
+   ---------------------
+   -- Restore_Context --
+   ---------------------
+   --
+   --  This procedure changes the return context of a preempted task.
+   --
+   --                    |        |               |       |
+   --  TCB_Ac.Stack_Ptr->|  Regs  |               |       |
+   --                    |        |               |       |
+   --                       ...                      ...
+   --                    |        |               |       |
+   --                    |        |               |Context|<-TCB_Ac.Stack_Ptr
+   --                    |        |<-Context.Esp->|       |
+   --                    |        |               |       |
+   --                    |        |               |       |
+   --                    |        |               |       |
+   --                      before                   after
+   --  The next time the task is scheduled will execute the final part of
+   --  Save_Context.
+   procedure Restore_Context (TCB_Ac  : System.Address;
+                              Context : access Jmp_Context) is
+
+      --  TCB_Ac points to the TCB of preempted task (a Kernel.TCB). The first
+      --  8 bytes are the tag and the top of the stack of preempted task.
+      type Beginning_Of_TCB is record
+         Tag : Unsigned_32;
+         Top_Of_Stack : Preempted_Task_Restore_Context_Stack_Ac;
+      end record;
+      type Beginning_Of_TCB_Ac is access Beginning_Of_TCB;
+
+      function UC  is
+        new Ada.Unchecked_Conversion (System.Address, Beginning_Of_TCB_Ac);
+      function UC  is
+        new Ada.Unchecked_Conversion (Unsigned_32,
+                                      Preempted_Task_Restore_Context_Stack_Ac);
+   begin
+
+      --  Set top of stack of the task to its new value
+      UC (TCB_Ac).Top_Of_Stack :=
+        UC (Context.Esp - Context.Return_Address'Size / 8
+           - Context.Ebp'Size / 8);
+
+      --  Create new return context
+      UC (TCB_Ac).Top_Of_Stack.all :=
+        (Return_Address => Context.Return_Address,
+         Ebp            => Context.Ebp,
+         Context_Stack  => Context.Context_Stack);
+
+      --  The context has been used to perform a non-local jump
+      Context.After_Jmp := 1;
+   end Restore_Context;
+
+end Non_Local_Jump;
diff --git a/marte_non_local_jump/non_local_jump.ads b/marte_non_local_jump/non_local_jump.ads
new file mode 100644 (file)
index 0000000..a9af143
--- /dev/null
@@ -0,0 +1,144 @@
+------------------------------------------------------------------------------
+--  ------------------         M a R T E   O S         -------------------  --
+------------------------------------------------------------------------------
+--                                                             {MARTE_VERSION}
+--
+--                      'N o n _ L o c a l _ J u m p'
+--
+--                                  Spec
+--
+--  File 'non_local_jump.ads'                                          By MAR
+--
+--  Non-local jumps for preempted tasks.
+--
+--  IMPORTANT: it must be compiled without any optimization!!
+--
+--  {MARTE_COPYRIGHT}
+--
+------------------------------------------------------------------------------
+--  {<MAR}
+--
+--  02-08-07:version operativa.
+--
+--  {MAR>} -------------------------------------------------------------------
+with System;
+with Basic_Integer_Types;
+
+package Non_Local_Jump is
+   pragma Optimize (Off);
+
+   type Jmp_Context is private;
+
+   -------------------
+   -- Save_Context --
+   -------------------
+   --
+   --  Context stores the information required to modify the stack of a
+   --  preempted task with 'Change_Return_Context_Of_Preempted_Task'.
+   --
+   --  This function stores in 'Context' the registers and its stack frame. This
+   --  information can be used for 'Restore_Context' to change the stack of the
+   --  task (when it is preempted) so that when it is scheduled again it returns
+   --  to the end of this function
+   --
+   procedure Save_Context (Context : access Jmp_Context);
+   pragma Export (C, Save_Context, "marte_nonlocaljmp_savecontext");
+
+   ------------------
+   --  After_Jump  --
+   ------------------
+   --
+   --  To be invoked after 'Save_Context'. If invoked after a direct invocation
+   --  to 'Save_Context', 'After_Jump' shall return 0 (False). If invoked after
+   --  returning from 'Save_Context' due to a call to 'Restore_Context',
+   --  'After_Jump' shall return 1 (True).
+   function After_Jump (Context : access Jmp_Context)
+                        return Basic_Integer_Types.Unsigned_32;
+   pragma Export (C, After_Jump, "marte_nonlocaljmp_afterjmp");
+
+   ---------------------
+   -- Restore_Context --
+   ---------------------
+   --
+   --  This procedure changes the return context of a preempted task.
+   --
+   --                    |        |               |       |
+   --  TCB_Ac.Stack_Ptr->|  Regs  |               |       |
+   --                    |        |               |       |
+   --                       ...                      ...
+   --                    |        |               |  ret  |<-TCB_Ac.Stack_Ptr
+   --                    |        |               |  ebp  |
+   --                    |        |<-Context.Esp->|  SC*  |
+   --                    |        |               |  SC*  |
+   --                    |        |               |  SC*  |
+   --                    |        |               |       |
+   --                      before                   after
+   --  SC*: stack frame of 'Save_Context'.
+   --
+   --  The next time the task is scheduled will execute the final part of
+   --  Save_Context.
+   --
+   --  The full process is the following: 'Save_Context' stores the registers
+   --  and its stack frame in 'Jmp_Context'. 'Restore_Context' restores that
+   --  context placing the stored frame in the same position of the stack it was
+   --  originally. Over this frame it is placed the value of the ebp register
+   --  and the address of label "1:" in 'Save_Context'.
+   --  When the task is scheduled again, the first instruction it executes is
+   --  "ret" in 'Processor_Registers.Context_Switch' and then the address of
+   --  label "1:" in 'Save_Context' is popped from the stack. Once in
+   --  'Save_Context', the ebp register is also popped and, with this
+   --  instruction, the registers and stack are in the same situation it was the
+   --  time that the contexts was stored, and then the final part of
+   --  'Save_Context' can be executed successfully.
+   procedure Restore_Context (TCB_Ac  : System.Address;
+                              Context : access Jmp_Context);
+   pragma Export (C, Restore_Context, "marte_nonlocaljmp_restorecontext");
+
+private
+
+   type Save_Context_Stack is array (1 .. 29) of  --  17->2005, 29->2007
+     Basic_Integer_Types.Unsigned_32;
+   type Save_Context_Stack_Ac is access Save_Context_Stack;
+   --  Stack of 'Save_Context' funcion. The frame created by 'Save_Context' is
+   --  16/28 integers long when no optimization is used for this function. The
+   --  total size is 17/29 because ebp register is also stored in the stack
+
+   --  A change in this record could affect the type
+   --  'marte_nonlocaljmp_context_t' defined in
+   --  'x86_arch/include/misc/marte_non_local_jmp.h'
+   type Jmp_Context is record
+      Return_Address     : System.Address;
+      --  The address of label "1:" inside 'Save_Context'. The task jumps to
+      --  this instruction from the 'ret' instruction in
+      --  'Processor_Registers.Context_Switch'.
+
+      Ebx                : Basic_Integer_Types.Unsigned_32;
+      Ecx                : Basic_Integer_Types.Unsigned_32;
+      Edx                : Basic_Integer_Types.Unsigned_32;
+      Esi                : Basic_Integer_Types.Unsigned_32;
+      Edi                : Basic_Integer_Types.Unsigned_32;
+      Ebp                : Basic_Integer_Types.Unsigned_32;
+      Eax                : Basic_Integer_Types.Unsigned_32;
+
+      Esp                : Basic_Integer_Types.Unsigned_32;  -- top of stack
+
+      After_Jmp          : Basic_Integer_Types.Unsigned_32;
+      -- 0 (False) after a direct invocation to 'Save_Context'. 1 (True) if
+      -- 'Restore_Context' has been invoked.
+
+      Context_Stack  : Save_Context_Stack;
+      --  Stack frame of 'Save_Context' funcion
+
+   end record;
+   pragma Volatile (Jmp_Context);
+   type Jmp_Context_Ac is access Jmp_Context;
+
+   type Preempted_Task_Restore_Context_Stack is record
+      Return_Address : System.Address;
+      Ebp            : Basic_Integer_Types.Unsigned_32;
+      Context_Stack  : Save_Context_Stack;
+   end record;
+   type Preempted_Task_Restore_Context_Stack_Ac is
+     access Preempted_Task_Restore_Context_Stack;
+
+end Non_Local_Jump;
diff --git a/marte_non_local_jump/non_local_jump_test.adb b/marte_non_local_jump/non_local_jump_test.adb
new file mode 100644 (file)
index 0000000..17282cd
--- /dev/null
@@ -0,0 +1,91 @@
+pragma Task_Dispatching_Policy (FIFO_Within_Priorities);\r
+with MaRTE_OS;\r
+with Text_IO; use Text_IO;\r
+with Ada.Unchecked_Conversion;\r
+with System;\r
+with Basic_Integer_Types; use Basic_Integer_Types;\r
+--  with Processor_Registers;\r
+with Non_Local_Jump;\r
+with System.Machine_Code; use System.Machine_Code;\r
+\r
+procedure Non_Local_Jump_Test is\r
+\r
+   pragma Linker_Options("eat_20.o");\r
+\r
+   procedure Eat_20;\r
+   pragma Import (C, Eat_20, "eat_20");\r
+\r
+   pragma Priority (10);\r
+\r
+   --  package PR renames Processor_Registers;\r
+   package PR renames Non_Local_Jump;\r
+\r
+   Cont : Integer := 0;\r
+   pragma Volatile (Cont);\r
+\r
+   TCB : System.Address := System.Null_Address;\r
+   pragma Volatile (TCB);\r
+\r
+   function Pthread_Self return System.Address;\r
+   pragma Import (C, Pthread_Self, "pthread_self");\r
+\r
+   Jmp_Buff : aliased PR.Jmp_Context;\r
+   pragma Volatile (Jmp_Buff);\r
+\r
+   procedure Por_Fastidiar2 (C : Integer) is\r
+   begin\r
+      loop\r
+\r
+         Put_Line (Integer'Image (C));\r
+         Eat_20;\r
+         --for I in 1 .. 20_000_000 loop\r
+         --   null;\r
+         --end loop;\r
+      end loop;\r
+   end Por_Fastidiar2;\r
+\r
+   procedure Por_Fastidiar1 (C : Integer) is\r
+   begin\r
+      Por_Fastidiar2 (C);\r
+   end Por_Fastidiar1;\r
+\r
+   --  tarea q se cambia su dirección de retorno\r
+   task Saltarina is\r
+      pragma Priority (5);\r
+   end Saltarina;\r
+\r
+   task body Saltarina is\r
+   begin\r
+      Put_Line ("hola2");\r
+      TCB := Pthread_Self;\r
+      loop\r
+         PR.Save_Context(Jmp_Buff'Access);\r
+         --  Asm ("int $3", No_Output_Operands, No_Input_Operands, "", True);\r
+         if PR.After_Jump (Jmp_Buff'Access) = 1 then\r
+            Put_Line ("---After Jump---");\r
+         else\r
+            Por_Fastidiar1 (Cont);\r
+            Put_Line ("---Not After Jump---");\r
+         end if;\r
+         Cont := Cont + 1;\r
+         Put_Line(" Cont:" & Integer'Image (Cont));\r
+      end loop;\r
+\r
+   exception\r
+      when E:others =>\r
+         Put_Line ("Exception in Saltarina");\r
+   end Saltarina;\r
+\r
+begin\r
+   loop\r
+      delay 2.0;\r
+      exit when Cont >= 5;\r
+\r
+      Put_Line ("Antes de cambiar retorno 3");\r
+      PR.Restore_Context (TCB, Jmp_Buff'Access);\r
+      Put_Line ("Desp de cambiar retorno 3");\r
+      --delay 1000000.0;\r
+   end loop;\r
+   Put_Line (Integer'Image (Jmp_Buff'Size/8));\r
+\r
+end Non_Local_Jump_Test;\r
index 4878f94c29ceaf9277dc2b4aadf8d645d3acfe86..3a732f4eaa755782acf5d2920eca5838ff5084bf 100644 (file)
@@ -171,6 +171,33 @@ int fosa_thread_get_cputime_clock
   return timer_create(clockid,&evp,timerid);
 }
 
+/**
+ * fosa_timer_create_with_receiver()
+ *
+ * Create a one-shot timer with a specific signal receiver thread
+ *
+ * This function creates a timer in the same way as fosa_timer_create,
+ * except that the signal generated when the timer expires is sent to
+ * the thread specified by receiver
+ *
+ * Returns 0 if successful; otherwise it returns an error code:
+ *     FOSA_EINVAL: the value of clockid or signal is invalid
+ *
+ *     FOSA_EAGAIN: the system lacks enough resources to create the timer
+ *
+ * Alternatively, in case of error the implementation is allowed to
+ * notify it to the system console and then terminate the FRSH
+ * implementation and dependant applications
+ **/
+ int fosa_timer_create_with_receiver
+      (fosa_clock_id_t clockid, frsh_signal_t signal, frsh_signal_info_t info,
+       fosa_timer_id_t *timerid, frsh_thread_id_t receiver)
+{
+  // in POSIX the receiver thread cannot be specified
+  return fosa_timer_create(clockid,signal,info,timerid);
+}
+
+
 /**
  * Delete a timer
  *
diff --git a/src_marte/fosa_long_jump.c b/src_marte/fosa_long_jump.c
new file mode 100644 (file)
index 0000000..04ebb66
--- /dev/null
@@ -0,0 +1,287 @@
+//----------------------------------------------------------------------
+//  Copyright (C) 2006 - 2007 by the FRESCOR consortium:
+//
+//    Universidad de Cantabria,              SPAIN
+//    University of York,                    UK
+//    Scuola Superiore Sant'Anna,            ITALY
+//    Kaiserslautern University,             GERMANY
+//    Univ. Politecnica  Valencia,           SPAIN
+//    Czech Technical University in Prague,  CZECH REPUBLIC
+//    ENEA                                   SWEDEN
+//    Thales Communication S.A.              FRANCE
+//    Visual Tools S.A.                      SPAIN
+//    Rapita Systems Ltd                     UK
+//    Evidence                               ITALY
+//
+//    See http://www.frescor.org
+//
+//        The FRESCOR project (FP6/2005/IST/5-034026) is funded
+//        in part by the European Union Sixth Framework Programme
+//        The European Union is not liable of any use that may be
+//        made of this code.
+//
+//
+//  based on previous work (FSF) done in the FIRST project
+//
+//   Copyright (C) 2005  Mälardalen University, SWEDEN
+//                       Scuola Superiore S.Anna, ITALY
+//                       Universidad de Cantabria, SPAIN
+//                       University of York, UK
+//
+// This file is part of FOSA (Frsh Operating System Abstraction)
+//
+// FOSA is free software; you can redistribute it and/or modify it
+// under terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option) any
+// later version.  FOSA is distributed in the hope that it will be
+// useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details. You should have received a
+// copy of the GNU General Public License along with FOSA; see file
+// COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,
+// Cambridge, MA 02139, USA.
+//
+// As a special exception, including FOSA header files in a file,
+// instantiating FOSA generics or templates, or linking other files
+// with FOSA objects to produce an executable application, does not
+// by itself cause the resulting executable application to be covered
+// by the GNU General Public License. This exception does not
+// however invalidate any other reasons why the executable file might be
+// covered by the GNU Public License.
+// -----------------------------------------------------------------------
+//fosa_long_jump.c
+//==============================================
+//  ********  ******    ********  **********
+//  **///// /**    **  **//////  /**     /**
+//  **      /**    ** /**        /**     /**
+//  ******* /**    ** /********* /**********
+//  **////  /**    ** ////////** /**//////**
+//  **      /**    **        /** /**     /**
+//  **      /**    **  ********  /**     /**
+//  //       /******/  ////////   //      //
+//
+// FOSA(Frescor Operating System Adaptation layer)
+//================================================
+
+#include <stdio.h>
+#include "fosa_long_jump.h"
+#include "fosa_configuration_parameters.h"
+#include "fosa_threads_and_signals.h"
+#include <marte_non_local_jmp.h>
+
+/**
+ * Global variables
+ */
+
+static int handler_installed=0;
+static frsh_thread_id_t handler_tid;
+
+/**
+ *  fosa_long_jump_save_context
+ *
+ *  Save the context of the current thread for a future long jump
+ *
+ *  This function stores in context the information required to modify
+ *  the stack of the calling thread so that a later long jump may be 
+ *  executed in the future to restore this context
+ *
+ *  This function stores in 'context' the registers and the stack
+ *  frame of the calling thread. This information can be used by
+ *  'restorecontext' to change the stack of the task so that when it
+ *  is scheduled again it returns to the end of this function
+ *
+ *  Depending on the underlying implementation, the first invocation
+ *  of this function for a given thread may also install a signal
+ *  handler or a signal handler thread that is capable of executing
+ *  the actions required to restore the context of a thread from the
+ *  appropriate context. For instance, in POSIX it is necesaray that
+ *  the context is restored from the same thread being restored,
+ *  usually from a signal handler of that thread.
+ *
+ *  Returns 0 if successful; otherwise it returns an error code:
+ *     FOSA_EINVAL: the value of context is invalid
+ *
+ *  Alternatively, in case of error the implementation is allowed to
+ *  notify it to the system console and then terminate the FRSH
+ *  implementation and dependant applications
+ */
+int fosa_long_jump_save_context
+   (fosa_long_jump_context_t * context) 
+{
+  if (context==NULL) {
+    return FOSA_EINVAL;
+  } else {
+    marte_nonlocaljmp_savecontext (&(context->marte_context));
+    context->tid=pthread_self();
+    return 0;
+  }
+}
+
+
+/**
+ *  fosa_long_jump_was_performed
+ *
+ *  Check whether the current thread suffered a long jump or not
+ *
+ *  This function should be invoked after fosa_long_jump_save_context
+ *  to determine whether the current thread is executing normally, or
+ *  has suffered a long jump to the point where the context was
+ *  saved. If invoked after a direct invocation to
+ *  fosa_long_jump_save_context, the function shall return 0. If
+ *  invoked after returning from fosa_long_jump_save_context due to a
+ *  call to fosa_long_jump_restore_context, the function shall return
+ *  1.
+ *
+ *  Returns 0 if successful; otherwise it returns an error code:
+ *     FOSA_EINVAL: the value of context is invalid
+ *
+ *  Alternatively, in case of error the implementation is allowed to
+ *  notify it to the system console and then terminate the FRSH
+ *  implementation and dependant applications
+ */
+int fosa_long_jump_was_performed
+(const fosa_long_jump_context_t * context, int * jumped) 
+{
+  if (context==NULL) {
+    return FOSA_EINVAL;
+  } else {
+    *jumped=marte_nonlocaljmp_afterjmp (&(context->marte_context));
+    return 0;
+  }  
+}
+
+
+/** 
+ * Body of the long-jump handler thread 
+ */
+
+void * fosa_long_jump_handler (void * arg) {
+
+  frsh_signal_t set[1];
+  frsh_signal_t sig;
+  frsh_signal_info_t siginfo;
+
+  fosa_long_jump_context_t *info;
+
+  // initialize signal handling
+  set[0]=FOSA_LONG_JUMP_SIGNAL;
+  if (fosa_set_accepted_signals(set, 1) !=0) {
+      printf("FRSH_ERR_INTERNAL_ERROR, Error setting the signal mask\n");
+      exit(1); 
+  }
+
+  // main thread loop  
+  while (1) {
+    // Wait for a budget overrun signal
+    if ((fosa_signal_wait(set, 1, &sig, &siginfo)) == -1) {
+      printf("FRSH_ERR_INTERNAL_ERROR, signal wait in long jump handler\n");
+      exit(1);
+    }
+    // Restore thread's context
+    printf("About to restore\n"); // remove
+    info=((fosa_long_jump_context_t*) (siginfo.sival_ptr));
+    marte_nonlocaljmp_restorecontext(info->tid,&(info->marte_context));
+    printf("Restored thread \n"); // remove
+  }
+}
+
+
+
+/**
+ *  fosa_long_jump_install_handler
+ *
+ *  Install a long jump handler for the calling thread
+ *
+ *  This function shall install a handler that is capable of causing a
+ *  long jump operation that restores the context of a thread to a
+ *  previously saved value. If the handler has already been installed
+ *  for this thread the previously installed handler will be used and
+ *  the call shall succeed.
+ *
+ *  The long-jump handler is waiting for a signal to notify that a
+ *  thread context should be restored. This signal must carry attached
+ *  to it a pointer to the variable where the thread context was
+ *  saved. The thread referenced in that context will have its
+ *  internal context restored to the point where it was saved. For
+ *  this restore operation to work properly, the program frame where
+ *  the thread saved its context must still be valid.
+ *
+ *  Depending on the implementation a given thread may also install a signal
+ *  handler or a signal handler thread that is capable of executing
+ *  the actions required to restore the context of a thread from the
+ *  appropriate context. For instance, in POSIX it is necesaray that
+ *  the context is restored from the same thread being restored,
+ *  usually from a signal handler of that thread.
+ *
+ *  The function shall store in the variable pointed to by signal the
+ *  identifier of the signal that must be used to notify the request
+ *  for a long jump to be executed. In the variable pointed to by
+ *  handler, it shall store the thread id to which the signal must be
+ *  sent. The signal must be sent with its attached information set to
+ *  a pointer to the variable of type fosa_long_jump_context_t where
+ *  the context of the thread to be restored was saved.
+ *
+ *  Returns 0 if successful; otherwise it returns an error code:
+ *     FOSA_EINVAL: the value of context is invalid
+ *     FOSA_ENOMEM: there are no resources to satisfy the call at this time
+ *
+ *  Alternatively, in case of error the implementation is allowed to
+ *  notify it to the system console and then terminate the FRSH
+ *  implementation and dependant applications
+ */
+int fosa_long_jump_install_handler
+(frsh_signal_t *signal, frsh_thread_id_t *handler)
+{
+  frsh_thread_attr_t attr;
+  int err;
+  
+  if (!handler_installed) {
+
+    handler_installed=1;
+
+    //////////////////////////////////////////////////
+    // create the long jump handler thread
+    //////////////////////////////////////////////////
+    
+    // Create the thread attributes object
+    err=frsh_thread_attr_init (&attr);
+    if (err != 0) {
+      printf("Error while initializing the attributes\n");
+      return err;
+    }
+    
+    // set the maximum priority level for the handler
+    err=fosa_thread_attr_set_prio (&attr,fosa_get_priority_max());
+    if (err != 0) {
+      printf("Error while setting schedparam\n");
+      return err;
+    }
+    
+    /* create the signal handler thread */
+    err = fosa_thread_create(&handler_tid, &attr, 
+                            fosa_long_jump_handler, NULL);
+    if (err) {
+      printf("pthread_create signal handler\n");
+      return err;
+    }
+    
+    // destroy the thread attributes object
+    err=frsh_thread_attr_destroy (&attr);
+    if (err != 0) {
+      printf("Error while destroying the attributes\n");
+      return err;
+    }
+  
+  } // if handler not installed
+
+  // return handler and signal information
+  *handler=handler_tid;
+  *signal=FOSA_LONG_JUMP_SIGNAL;
+  return 0;
+
+}
+
+
+
+/*@}*/
+