+//----------------------------------------------------------------------
+// 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;
+
+}
+
+
+
+/*@}*/
+