(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()
*
// 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
--- /dev/null
+//----------------------------------------------------------------------
+// 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 */
#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
#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 //////////////////////
#define FOSA_COND_T_OPAQUE int
+
/*********
* ADS
*********/
/*@}*/
+/*********************
+ * 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_
--- /dev/null
+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*
+
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+void eat_20() {
+ int i;
+ for (i=0; i<200000000; i++){
+ i++;
+ i--;
+ }
+}
--- /dev/null
+void eat_20();
--- /dev/null
+#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
--- /dev/null
+/*----------------------------------------------------------------------------\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
--- /dev/null
+------------------------------------------------------------------------------
+-- ------------------ 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;
--- /dev/null
+------------------------------------------------------------------------------
+-- ------------------ 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;
--- /dev/null
+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
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
*
--- /dev/null
+//----------------------------------------------------------------------
+// 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;
+
+}
+
+
+
+/*@}*/
+