]> rtime.felk.cvut.cz Git - frescor/fosa.git/blob - src_marte_os/tests/test_non_local_jump/simple_test_non_local_jump.c
Makefile: Add missing header file
[frescor/fosa.git] / src_marte_os / tests / test_non_local_jump / simple_test_non_local_jump.c
1 // -----------------------------------------------------------------------
2 //  Copyright (C) 2006 - 2009 FRESCOR consortium partners:
3 //
4 //    Universidad de Cantabria,              SPAIN
5 //    University of York,                    UK
6 //    Scuola Superiore Sant'Anna,            ITALY
7 //    Kaiserslautern University,             GERMANY
8 //    Univ. Politécnica  Valencia,           SPAIN
9 //    Czech Technical University in Prague,  CZECH REPUBLIC
10 //    ENEA                                   SWEDEN
11 //    Thales Communication S.A.              FRANCE
12 //    Visual Tools S.A.                      SPAIN
13 //    Rapita Systems Ltd                     UK
14 //    Evidence                               ITALY
15 //
16 //    See http://www.frescor.org for a link to partners' websites
17 //
18 //           FRESCOR project (FP6/2005/IST/5-034026) is funded
19 //        in part by the European Union Sixth Framework Programme
20 //        The European Union is not liable of any use that may be
21 //        made of this code.
22 //
23 //
24 //  based on previous work (FSF) done in the FIRST project
25 //
26 //   Copyright (C) 2005  Mälardalen University, SWEDEN
27 //                       Scuola Superiore S.Anna, ITALY
28 //                       Universidad de Cantabria, SPAIN
29 //                       University of York, UK
30 //
31 //   FSF API web pages: http://marte.unican.es/fsf/docs
32 //                      http://shark.sssup.it/contrib/first/docs/
33 //
34 //   This file is part of FOSA (Frsh Operating System Adaption)
35 //
36 //  FOSA is free software; you can redistribute it and/or modify it
37 //  under terms of the GNU General Public License as published by the
38 //  Free Software Foundation; either version 2, or (at your option) any
39 //  later version.  FOSA is distributed in the hope that it will be
40 //  useful, but WITHOUT ANY WARRANTY; without even the implied warranty
41 //  of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
42 //  General Public License for more details. You should have received a
43 //  copy of the GNU General Public License along with FOSA; see file
44 //  COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,
45 //  Cambridge, MA 02139, USA.
46 //
47 //  As a special exception, including FOSA header files in a file,
48 //  instantiating FOSA generics or templates, or linking other files
49 //  with FOSA objects to produce an executable application, does not
50 //  by itself cause the resulting executable application to be covered
51 //  by the GNU General Public License. This exception does not
52 //  however invalidate any other reasons why the executable file might be
53 //  covered by the GNU Public License.
54 // -----------------------------------------------------------------------
55 // 11-Jul-2007 SANGORRIN change calibrate and eat because it didn't work for
56 // MaRTE OS linux_arch
57 // 13-Jul-2007 SANGORRIN substitute calibrate for a new eat that I have added
58 // -----------------------------------------------------------------------
59 #include <stdio.h>
60 #include <stdlib.h>
61 #include <unistd.h>
62 #include <time.h>
63
64 //#include <string.h>
65 //#include <errno.h>
66 //#include <pthread.h>
67 //#include <sched.h>
68 //#include <signal.h>
69 //#include <frsh.h>
70
71 #include "fosa.h"
72
73 #include "misc/marte_non_local_jmp.h"
74
75 /************************/
76 /** Constants and types */
77 /************************/
78
79 #define BUDGET_OVERRUN_SIGNAL SIGRTMIN+3
80 #define RT_ERROR_SIGWAIT -2
81 #define RT_ERROR_TIMER   -3
82
83 typedef struct {
84   fosa_thread_id_t tid;
85   marte_nonlocaljmp_context_t *context_ptr;
86   int dummy;
87 } budget_timer_info_t;
88
89
90 /************************/
91 /** Global Variables    */
92 /************************/
93
94 static marte_nonlocaljmp_context_t context;
95 static int error_status;
96
97
98 /************************/
99 /** Prototypes          */
100 /************************/
101
102 static void * thread_body(void *arg);
103 static void * signal_handler_thread (void * arg);
104
105
106 /************************************************************************/
107 /*                             Main program                             */
108 /************************************************************************/
109
110 int main()
111 {
112     fosa_signal_t set[1];
113     fosa_thread_attr_t attr;
114
115     fosa_thread_id_t tid1, tid2;
116     int terror = 0;
117
118     // Print test header
119     printf("\n");
120     printf("This test checks the ability to make long jumps in MaRTE OS\n");
121     printf("A periodic workload consumes 1ms or 2ms (every 5 iterations)\n");
122     printf("The budget is set to 1.4ms; when exceeded, the operation is aborted\n");
123     printf("\n");
124
125     // set signal mask
126     set[0]=BUDGET_OVERRUN_SIGNAL;
127     if (fosa_set_accepted_signals(set, 1) !=0) {
128       printf ("Error while setting the signal mask\n"); 
129       exit (1);
130     }
131
132     // Create the thread attributes object
133     if (fosa_thread_attr_init (&attr) != 0) {
134       printf("Error while initializing the attributes\n");
135       exit(1);
136     }
137     
138     if (fosa_thread_attr_set_prio (&attr,fosa_get_priority_max()-2) != 0) {
139       printf("Error while setting schedparam\n");
140       exit(1);
141     }
142
143
144     /* create the signal handler thread */
145     terror = fosa_thread_create(&tid1, &attr, signal_handler_thread, NULL);
146     if (terror) {
147         printf("Error in pthread_create signal handler\n");
148         exit(1);
149     }
150
151     // set priority of periodic thread
152     if (fosa_thread_attr_set_prio (&attr,fosa_get_priority_min()+3) != 0) {
153       printf("Error while setting schedparam\n");
154       exit(1);
155     }
156
157     /* create the periodic thread */
158     terror = fosa_thread_create(&tid2, &attr, thread_body, NULL);
159     if (terror) {
160         printf("Error in pthread_create periodic thread\n");
161         exit(1);
162     }
163
164     printf("Main goes to sleep...\n");
165     sleep(20000);
166
167     return 0;
168 }
169
170 // work to be aborted if too long
171 void work() {
172   static int i=0;
173   fosa_rel_time_t exec_time = fosa_msec_to_rel_time(1000); // 1 second
174
175   i++;
176   printf("start work (eat 1s) %d\n",i); 
177   // regular code 
178   // eat one second of budget 
179   fosa_eat(&exec_time); 
180   // every five cycles eat an additional one second of budget */
181   if (i%5==0) { 
182     printf("start eating 1s more\n");
183     fosa_eat(&exec_time); 
184   } 
185   printf("finish work\n");
186 }
187
188
189
190 /* ------------------------------------------------------------ */
191 /** Body of periodic thread that consumes budget */
192
193 static void * thread_body(void *thread_arg)
194 {
195     fosa_rel_time_t period = fosa_msec_to_rel_time(2500);
196     fosa_rel_time_t budget = fosa_msec_to_rel_time(1400);
197     fosa_abs_time_t activation_time, after_activation_time;
198     fosa_rel_time_t elapsed_time;
199     struct timespec activation_time_tspec;
200
201     fosa_timer_id_t timerid;
202     fosa_clock_id_t clockid;
203     budget_timer_info_t timerinfo;
204     fosa_signal_info_t siginfo;
205     int i=0;
206
207     timerinfo.tid=pthread_self();
208     timerinfo.context_ptr=&context;
209
210     fosa_clock_get_time(FOSA_CLOCK_REALTIME,&activation_time);
211
212     if (fosa_thread_get_cputime_clock(timerinfo.tid,&clockid) !=0) {
213         error_status=RT_ERROR_TIMER;
214         pthread_exit ( (void*)&error_status);
215     }
216
217     // create budget timer
218     siginfo.sival_ptr=(void *)(&timerinfo);
219     if (fosa_timer_create (clockid,BUDGET_OVERRUN_SIGNAL,siginfo,&timerid)
220         != 0) 
221     {
222         error_status=RT_ERROR_TIMER;
223         pthread_exit ( (void*)&error_status);
224     }
225
226     printf("Start periodic thread body with 1400ms budget\n");
227    
228     // main loop
229     while(1) {
230       
231         // set the budget timer
232         if (fosa_rel_timer_arm(timerid, &budget) != 0) {
233             error_status=RT_ERROR_TIMER;
234             pthread_exit ( (void*)&error_status);
235         }
236  
237         printf("Begin thread at: %ld msec\n", 
238                fosa_abs_time_to_msec(activation_time) );
239         i++;
240         timerinfo.dummy=i;
241
242         // save context
243       
244         marte_nonlocaljmp_savecontext(&context);
245         printf ("context saved\n");
246
247         if (marte_nonlocaljmp_afterjmp(&context)==0) { 
248             work();
249         } else { 
250             // code executed if asynchronous jump instruction invoked */
251             printf("Work was aborted\n"); 
252         } 
253
254         //printf("after block %d\n",marte_nonlocaljmp_afterjmp(&context));
255         printf("Work block was finished\n");
256         fosa_clock_get_time(FOSA_CLOCK_REALTIME, &after_activation_time);
257         elapsed_time = fosa_abs_time_extract_interval
258           (activation_time, after_activation_time);
259         printf("End   thread. Elapsed: %ld msec\n", 
260                fosa_rel_time_to_msec(elapsed_time) );
261
262         // sleep for a while
263         activation_time = fosa_abs_time_incr(activation_time, period);
264         activation_time_tspec = fosa_abs_time_to_timespec(activation_time);
265         
266         clock_nanosleep(FOSA_CLOCK_REALTIME,TIMER_ABSTIME,
267                         &activation_time_tspec, NULL);
268     } // while
269 }
270
271
272 /*----------------------------------------------------------------------*/
273
274 /** Body of signal handler thread 
275  * The signal mask is assumed to be inherited from the parent
276  */
277
278 void * signal_handler_thread (void * arg) {
279
280   fosa_signal_t set[1];
281   fosa_signal_t sig;
282   fosa_signal_info_t siginfo;
283
284   budget_timer_info_t *info;
285
286   // Wait for a budget overrun signal
287   set[0]=BUDGET_OVERRUN_SIGNAL;
288   while (1) {
289     if ((fosa_signal_wait(set, 1, &sig, &siginfo)) == -1) {
290       error_status=RT_ERROR_SIGWAIT;
291       pthread_exit ( (void*)&error_status);
292     }
293     // Restore periodic thread's context
294     printf("About to restore context\n");
295     info=((budget_timer_info_t*) (siginfo.sival_ptr));
296     marte_nonlocaljmp_restorecontext(info->tid,info->context_ptr);
297     printf("Restored thread %d\n",info->dummy);
298   }
299 }