-//----------------------------------------------------------------------
-// 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 FRSH (FRescor ScHeduler)
-//
-// FRSH 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. FRSH 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 FRSH; see file
-// COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,
-// Cambridge, MA 02139, USA.
-//
-// As a special exception, including FRSH header files in a file,
-// instantiating FRSH generics or templates, or linking other files
-// with FRSH 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.
-// -----------------------------------------------------------------------
+/*
+** testbench_long_jump.c
+**
+** Made by (Miguel marciano)
+** Login <miguel@namir.ctr.unican.es>
+**
+** Started on Fri Nov 23 11:42:09 2007 Miguel marciano
+** Last update Sun May 12 01:17:25 2002 Speed Blue
+*/
#include <stdio.h>
+#include <string.h>
#include <stdlib.h>
#include <unistd.h>
-#include <time.h>
-
-//#include <string.h>
-//#include <errno.h>
-//#include <pthread.h>
-//#include <sched.h>
-//#include <signal.h>
-//#include <frsh.h>
+#include <time.h> // For clock_nanosleep
+#include "frsh_error.h"
+#include "fosa.h"
#include "frsh_fosa.h"
-#include "fosa_threads_and_signals.h"
-#include "fosa_clocks_and_timers.h"
-#include "fosa_configuration_parameters.h"
-
#include "timespec_operations.h"
-#include "fosa_long_jump.h"
-
-/************************/
-/** Constants and types */
-/************************/
+/*************************/
+/* D E F I N I T I O N S */
+/*************************/
+#define PERIODIC_THREAD_PRIORITY (fosa_get_priority_min() + 3)
+#define MAIN_THREAD_PRIORITY (fosa_get_priority_min() + 5)
-#define RT_ERROR_SIGWAIT -2
-#define RT_ERROR_TIMER -3
-#define RT_ERROR_HANDLER -4
+/*************************/
+/* P R O T O T Y P E S */
+/*************************/
+static void *periodic_code(void *thread_arg);
-/************************/
-/** Global Variables */
-/************************/
-
+/**********************************/
+/* S T A T I C V A R I A B L E S */
+/**********************************/
static fosa_long_jump_context_t context;
-static int error_status = 0;
-
-
-/************************/
-/** Prototypes */
-/************************/
+static void work_under_a_interruptible_budget();
-static void * thread_body(void *arg);
-static void work();
-
-
-/************************************************************************/
-/* Main program */
-/************************************************************************/
int main()
{
- //frsh_signal_t set[1];
- frsh_thread_attr_t attr;
-
- frsh_thread_id_t tid_periodic_thread;
- int terror = 0;
+ int terror = -1;
+ frsh_thread_attr_t periodic_attr;
frsh_signal_t signal_set[1];
+ frsh_thread_id_t periodic_tid;
-
- memset(&attr, 0, sizeof(attr) );
- memset(&tid_periodic_thread, 0, sizeof(tid_periodic_thread) );
memset(&context, 0, sizeof(context) );
+
+ memset(&periodic_attr, 0, sizeof(periodic_attr) );
memset(&signal_set, 0, sizeof(signal_set) );
+ memset(&periodic_tid, 0, sizeof(periodic_tid) );
- /* Create the thread attributes object and assign the new thread a
- priority lower than the main */
- if (frsh_thread_attr_init (&attr) != 0) {
- printf("Error while initializing the attributes\n");
- exit(1);
- }
-
- // set priority of periodic thread
- if (fosa_thread_attr_set_prio (&attr,fosa_get_priority_min()+3) != 0) {
- printf("Error while setting schedparam\n");
- exit(1);
- }
- /* We set the priority of this main thread to a lever higher */
- /* than the future periodic thread. */
- /*************************************************************/
- if (fosa_thread_set_prio(fosa_thread_self(), fosa_get_priority_min() + 4) )
- {
- printf("Error while changing main's priority\n");
- exit(1);
- }
+ /* We set the signal mask */
+ signal_set[0] = FOSA_LONG_JUMP_SIGNAL;
+ PRW( fosa_set_accepted_signals(signal_set, 1) );
- /* create the periodic thread */
- /******************************/
- terror = fosa_thread_create(&tid_periodic_thread, &attr, thread_body, NULL);
- if (terror) {
- printf("pthread_create periodic thread\n");
- exit(1);
- }
+ /* We create a new thread with a given priority */
+ PRW( frsh_thread_attr_init(&periodic_attr) );
+ PRW( fosa_thread_attr_set_prio(&periodic_attr, PERIODIC_THREAD_PRIORITY) );
+ PRW( fosa_thread_create(&periodic_tid, &periodic_attr, periodic_code, NULL) );
printf("Main goes to sleep...\n");
- sleep(20000);
+
+ sleep(2000);
return 0;
}
+// ------------------------------------------------------------------------
+static void *periodic_code(void *thread_arg)
+{
+ int terror = -1;
-/* ------------------------------------------------------------ */
-/** Body of periodic thread that consumes budget */
+ struct timespec period = {2, 500000000}; // 2.5 secs
+ frsh_thread_id_t jump_handler_thread;
-static void * thread_body(void *thread_arg)
-{
- struct timespec period={2,500000000}; // 2.5 seconds
- struct timespec activation_time, old_activation_time;
- struct timespec budget ={1,400000000}; // 1.4 seconds
- fosa_timer_id_t timerid;
- fosa_clock_id_t clockid;
- frsh_signal_info_t siginfo;
- frsh_signal_t signal;
- frsh_thread_id_t handler;
- int jumped;
- int err;
-
-
- fosa_clock_get_time(FOSA_CLOCK_REALTIME, &activation_time);
-
- if (fosa_thread_get_cputime_clock(pthread_self(),&clockid) !=0) {
- error_status=RT_ERROR_TIMER;
- pthread_exit ( (void*)&error_status);
- }
+ frsh_signal_t jump_signal;
+ frsh_signal_info_t jump_signal_info;
+
+ fosa_clock_id_t clock_id;
+ fosa_timer_id_t jump_timer;
+
+ memset(&jump_signal, 0, sizeof(jump_signal) );
+ memset(&jump_signal_info, 0, sizeof(jump_signal_info) );
+ memset(&jump_handler_thread, 0, sizeof(jump_handler_thread) );
+ memset(&clock_id, 0, sizeof(clock_id) );
+ memset(&jump_timer, 0, sizeof(jump_timer) );
- // install long jump handler
- if (fosa_long_jump_install_handler(&signal,&handler)!=0)
- {
- error_status=RT_ERROR_HANDLER;
- pthread_exit ( (void*)&error_status);
- }
-
- // create budget timer
- siginfo.sival_ptr=(void *)(&context);
- if (fosa_timer_create_with_receiver
- (clockid,signal,siginfo,&timerid,handler) != 0)
+
+ /* We install a long jump handler */
+ /* - This creates the thread that will wait for */
+ /* FOSA_JUMP_SIGNAL */
+ /************************************************/
+ PXW( fosa_long_jump_install_handler(&jump_signal, &jump_handler_thread) );
+
+ /* We create a budget timer using the thread's CPU clock */
+ /* */
+ /* When the timer expires: */
+ /* - Triggers the signal corresponding to signal jump */
+ /* - Provides a pointer to the context in siginfo. */
+ /* */
+ /* This signal is delivered to the handler thread. */
+ /*********************************************************/
+ PXW( fosa_thread_get_cputime_clock( fosa_thread_self(), &clock_id) );
+ jump_signal_info.sival_ptr = &context;
+ PXW( fosa_timer_create_with_receiver(clock_id, jump_signal, jump_signal_info,
+ &jump_timer, jump_handler_thread) );
+
+
+ /* Periodic loop */
+ /*****************/
+ while (1)
{
- error_status=RT_ERROR_TIMER;
- pthread_exit ( (void*)&error_status);
- }
+ int jumped = -1;
+ struct timespec budget = {1, 400000000}; // 1.4 secs
+ struct timespec activation_time = {-1, -1};
+ struct timespec old_activation_time = {-1, -1};
+
- printf("Start periodic thread body\n");
-
- // main loop
- while(1) {
jumped = 0;
-
- // set the budget timer
- if (fosa_timer_arm(timerid, false, &budget) != 0) {
- error_status=RT_ERROR_TIMER;
- pthread_exit ( (void*)&error_status);
+
+ /* For statistical purposes we read the activation time */
+ PXW( fosa_clock_get_time(FOSA_CLOCK_REALTIME, &activation_time) );
+
+
+
+ /* Start of the interruptible block */
+ /************************************/
+
+ /* We arm the jump_timer */
+ PXW( fosa_timer_arm(jump_timer, false, &budget) );
+
+ /* This is the point where the jump returns */
+ PXW( fosa_long_jump_save_context(&context) );
+
+ /* Query if we come from a jump */
+ PXW( fosa_long_jump_was_performed(&context, &jumped) );
+ if (!jumped)
+ {
+ /* HERE COMES THE WORK THAT CAN BE INTERRUPTED */
+ work_under_a_interruptible_budget();
+ printf("NOT JUMPPED\n");
}
-
- printf("Begin thread main loop at %d,%d\n",(int)activation_time.tv_sec,
- (int)(activation_time.tv_nsec/1000000));
-
- // save context
-
- err=fosa_long_jump_save_context(&context);
- if (err!=0) {
- error_status=RT_ERROR_HANDLER;
- pthread_exit ( (void*)&error_status);
+ else
+ {
+ printf("JUMPPPPPEEED\n");
}
- err=fosa_long_jump_was_performed(&context,&jumped);
- if (err!=0) {
- error_status=RT_ERROR_HANDLER;
- pthread_exit ( (void*)&error_status);
- }
- if (!jumped) {
- work();
- } else {
- // code executed if asynchronous jump instruction invoked */
- printf("Aborted thread\n");
- }
-
- printf("after abortable block\n");
- fosa_clock_get_time(FOSA_CLOCK_REALTIME,&old_activation_time);
- decr_timespec(&old_activation_time,&activation_time);
- printf("End thread %6.3f\n",old_activation_time.tv_sec+(float)
- (float)old_activation_time.tv_nsec/1000000000.0);
- // sleep for a while
- incr_timespec(&activation_time,&period);
- clock_nanosleep(FOSA_CLOCK_REALTIME,TIMER_ABSTIME,
- &activation_time,&old_activation_time);
- } // while
+
+ /* End of interruptible work */
+ /*****************************/
+
+ printf("After interruptible block\n");
+
+ /* Now we measure the time duration of the block */
+ /*************************************************/
+ PXW( fosa_clock_get_time(FOSA_CLOCK_REALTIME, &old_activation_time) );
+ decr_timespec(&old_activation_time, &activation_time);
+ printf("Execution time: %6.3f\n", t2d(old_activation_time) );
+
+ /* And we program the next loop */
+ incr_timespec(&activation_time, &period);
+ clock_nanosleep(FOSA_CLOCK_REALTIME, TIMER_ABSTIME, &activation_time,
+ &old_activation_time);
+ }
+
+ return NULL;
}
+// ------------------------------------------------------------------------------
-// ---------------------------------------------------------------------
-
-// work to be aborted if too long
-static void work()
+static void work_under_a_interruptible_budget()
{
- static int i=0;
- struct timespec exec_time={1,0}; // 1 second
+ static int i = 0;
+ struct timespec exec_time = {1, 0}; // 1 seg
i++;
- printf("start regular code %d\n",i);
- // regular code
- // eat one second of budget
- frsh_eat(&exec_time);
- // every five cycles eat an additional one second of budget */
- if (i%5==0) {
- frsh_eat(&exec_time);
- frsh_eat(&exec_time);
- frsh_eat(&exec_time);
- frsh_eat(&exec_time);
- frsh_eat(&exec_time);
- }
+ printf("Start regular work\n");
+
+ frsh_eat(&exec_time);
+
+ /* Once in every 5 executions we work over the budget */
+ if (i % 5 == 0)
+ {
+ frsh_eat(&exec_time);
+ frsh_eat(&exec_time);
+ frsh_eat(&exec_time);
+ frsh_eat(&exec_time);
+ frsh_eat(&exec_time);
+ frsh_eat(&exec_time);
+ }
+
+ printf("End regular work\n");
+
}
** Started on Fri Nov 23 11:42:09 2007 Miguel marciano
** Last update Sun May 12 01:17:25 2002 Speed Blue
*/
+
+/*
+ TO DO:
+
+ - Define a pthread_join equivalent in FOSA (and also the detachable
+ argument).
+ - Define a clock_nanosleep equivalent in FOSA.
+
+*/
+
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "frsh_fosa.h"
#include "timespec_operations.h"
+
+
/*************************/
/* D E F I N I T I O N S */
/*************************/
-#define PERIODIC_THREAD_PRIORITY (fosa_get_priority_min() + 3)
-#define MAIN_THREAD_PRIORITY (fosa_get_priority_min() + 5)
+#define PERIODIC_THREAD_PRIORITY (fosa_get_priority_min() + 5)
+#define MAIN_THREAD_PRIORITY (fosa_get_priority_min() + 3)
+
+#define NUMBER_OF_JUMPS 5
+typedef struct _results_t
+{
+ double first_jump_interval_ms;
+ double average_jump_interval_ms;
+ double min_jump_interval_ms;
+ double max_jump_interval_ms;
+ double total_jump_interval_ms;
+ int number_of_jumps;
+} results_t;
/*************************/
/* P R O T O T Y P E S */
static fosa_long_jump_context_t context;
static void work_under_a_interruptible_budget();
+struct timespec before_jump_timestamp = {-1, -1};
+
int main()
{
frsh_thread_attr_t periodic_attr;
frsh_signal_t signal_set[1];
frsh_thread_id_t periodic_tid;
+ results_t results;
memset(&context, 0, sizeof(context) );
memset(&periodic_attr, 0, sizeof(periodic_attr) );
memset(&signal_set, 0, sizeof(signal_set) );
memset(&periodic_tid, 0, sizeof(periodic_tid) );
-
+ memset(&results, 0, sizeof(results) );
/* We set the signal mask */
signal_set[0] = FOSA_LONG_JUMP_SIGNAL;
PRW( fosa_set_accepted_signals(signal_set, 1) );
/* We create a new thread with a given priority */
+ PRW( fosa_thread_set_prio(fosa_thread_self(), MAIN_THREAD_PRIORITY) );
+
PRW( frsh_thread_attr_init(&periodic_attr) );
PRW( fosa_thread_attr_set_prio(&periodic_attr, PERIODIC_THREAD_PRIORITY) );
- PRW( fosa_thread_create(&periodic_tid, &periodic_attr, periodic_code, NULL) );
+ PRW( fosa_thread_create(&periodic_tid, &periodic_attr, periodic_code, &results) );
- printf("Main goes to sleep...\n");
+ printf("Main waits for the periodic code to finish...\n");
+ pthread_join(periodic_tid, NULL);
+
+ results.average_jump_interval_ms = results.total_jump_interval_ms/results.number_of_jumps;
- sleep(2000);
+ printf("------------ RESULTS -------------\n");
+ printf("First Time: %6.3f ms Max Time: %6.3f ms Min Time: %6.3f ms\n",
+ results.first_jump_interval_ms, results.max_jump_interval_ms, results.min_jump_interval_ms);
+ printf("Average_time: %6.3f ms Total jumps: %d\n", results.average_jump_interval_ms, results.number_of_jumps);
+ printf("End of test\n");
return 0;
}
fosa_clock_id_t clock_id;
fosa_timer_id_t jump_timer;
+ /* testbench data */
+ results_t *results;
+ int first_time = 1;
+
+
memset(&jump_signal, 0, sizeof(jump_signal) );
memset(&jump_signal_info, 0, sizeof(jump_signal_info) );
memset(&jump_handler_thread, 0, sizeof(jump_handler_thread) );
memset(&clock_id, 0, sizeof(clock_id) );
memset(&jump_timer, 0, sizeof(jump_timer) );
+ results = (results_t *) thread_arg;
/* We install a long jump handler */
/* - This creates the thread that will wait for */
PXW( fosa_timer_create_with_receiver(clock_id, jump_signal, jump_signal_info,
&jump_timer, jump_handler_thread) );
-
+ results->number_of_jumps = 0;
+
/* Periodic loop */
/*****************/
- while (1)
+ while (results->number_of_jumps < NUMBER_OF_JUMPS)
{
int jumped = -1;
struct timespec budget = {1, 400000000}; // 1.4 secs
- struct timespec activation_time = {-1, -1};
- struct timespec old_activation_time = {-1, -1};
+ struct timespec old_activation_timestamp = {-1, -1};
+ struct timespec activation_timestamp = {-1, -1};
+ struct timespec after_jump_timestamp = {-1, -1 };
+ double jump_interval_ms = 0.0;
+
+ /* We initialise variables */
jumped = 0;
+ memset(&before_jump_timestamp, 0, sizeof(before_jump_timestamp) );
/* For statistical purposes we read the activation time */
- PXW( fosa_clock_get_time(FOSA_CLOCK_REALTIME, &activation_time) );
-
-
+ fosa_clock_get_time(FOSA_CLOCK_REALTIME, &old_activation_timestamp);
/* Start of the interruptible block */
/************************************/
/* We arm the jump_timer */
- PXW( fosa_timer_arm(jump_timer, false, &budget) );
+ fosa_timer_arm(jump_timer, false, &budget);
/* This is the point where the jump returns */
- PXW( fosa_long_jump_save_context(&context) );
+ fosa_long_jump_save_context(&context);
/* Query if we come from a jump */
- PXW( fosa_long_jump_was_performed(&context, &jumped) );
+ fosa_long_jump_was_performed(&context, &jumped);
if (!jumped)
{
/* HERE COMES THE WORK THAT CAN BE INTERRUPTED */
work_under_a_interruptible_budget();
- printf("NOT JUMPPED\n");
+ printf("We should not arrive here \n");
+ exit(1);
}
else
{
- printf("JUMPPPPPEEED\n");
+ fosa_clock_get_time(FOSA_CLOCK_REALTIME, &after_jump_timestamp);
+
+ results->number_of_jumps++;
+ decr_timespec(&after_jump_timestamp, &before_jump_timestamp);
+ jump_interval_ms = t2d(after_jump_timestamp) * 1000;
+
+ if (first_time)
+ {
+ results->first_jump_interval_ms = jump_interval_ms;
+ results->max_jump_interval_ms = jump_interval_ms;
+ results->min_jump_interval_ms = jump_interval_ms;
+
+ first_time = 0;
+ }
+ results->total_jump_interval_ms += jump_interval_ms;
+
+ if (jump_interval_ms > results->max_jump_interval_ms)
+ {
+ results->max_jump_interval_ms = jump_interval_ms;
+ }
+
+ if (jump_interval_ms < results->min_jump_interval_ms)
+ {
+ results->min_jump_interval_ms = jump_interval_ms;
+ }
+
+ printf("Jump Iteration: %d\n", results->number_of_jumps);
}
/* End of interruptible work */
/*****************************/
-
printf("After interruptible block\n");
/* Now we measure the time duration of the block */
/*************************************************/
- PXW( fosa_clock_get_time(FOSA_CLOCK_REALTIME, &old_activation_time) );
- decr_timespec(&old_activation_time, &activation_time);
- printf("Execution time: %6.3f\n", t2d(old_activation_time) );
+ fosa_clock_get_time(FOSA_CLOCK_REALTIME, &activation_timestamp);
+ decr_timespec(&activation_timestamp, &old_activation_timestamp);
+ printf("Execution time: %6.3f\n", t2d(activation_timestamp) );
/* And we program the next loop */
- incr_timespec(&activation_time, &period);
- clock_nanosleep(FOSA_CLOCK_REALTIME, TIMER_ABSTIME, &activation_time,
- &old_activation_time);
+ incr_timespec(&old_activation_timestamp, &period);
+ clock_nanosleep(FOSA_CLOCK_REALTIME, TIMER_ABSTIME, &activation_timestamp,
+ &old_activation_timestamp);
}
+
+
return NULL;
}
static void work_under_a_interruptible_budget()
{
- static int i = 0;
struct timespec exec_time = {1, 0}; // 1 seg
- i++;
printf("Start regular work\n");
frsh_eat(&exec_time);
- /* Once in every 5 executions we work over the budget */
- if (i % 5 == 0)
+ /* This must be measured */
+ while(1)
{
- frsh_eat(&exec_time);
- frsh_eat(&exec_time);
- frsh_eat(&exec_time);
- frsh_eat(&exec_time);
- frsh_eat(&exec_time);
- frsh_eat(&exec_time);
+ fosa_clock_get_time(FOSA_CLOCK_REALTIME, &before_jump_timestamp);
}
- printf("End regular work\n");
-
}