]> rtime.felk.cvut.cz Git - frescor/fosa.git/blob - src_marte/tests/test_non_local_jump/simple_test_non_local_jump.c
Migrating FOSA trunk to d-ac2v2. Phase 1 moving FRSH-FOSA to FOSA
[frescor/fosa.git] / src_marte / tests / test_non_local_jump / simple_test_non_local_jump.c
1 //----------------------------------------------------------------------
2 //  Copyright (C) 2006 - 2007 by the FRESCOR consortium:
3 //
4 //    Universidad de Cantabria,              SPAIN
5 //    University of York,                    UK
6 //    Scuola Superiore Sant'Anna,            ITALY
7 //    Kaiserslautern University,             GERMANY
8 //    Univ. Politecnica  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
17 //
18 //        The 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 // This file is part of FRSH (FRescor ScHeduler)
32 //
33 // FRSH is free software; you can redistribute it and/or modify it
34 // under terms of the GNU General Public License as published by the
35 // Free Software Foundation; either version 2, or (at your option) any
36 // later version.  FRSH is distributed in the hope that it will be
37 // useful, but WITHOUT ANY WARRANTY; without even the implied warranty
38 // of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
39 // General Public License for more details. You should have received a
40 // copy of the GNU General Public License along with FRSH; see file
41 // COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,
42 // Cambridge, MA 02139, USA.
43 //
44 // As a special exception, including FRSH header files in a file,
45 // instantiating FRSH generics or templates, or linking other files
46 // with FRSH objects to produce an executable application, does not
47 // by itself cause the resulting executable application to be covered
48 // by the GNU General Public License. This exception does not
49 // however invalidate any other reasons why the executable file might be
50 // covered by the GNU Public License.
51 // -----------------------------------------------------------------------
52 // 11-Jul-2007 SANGORRIN change calibrate and eat because it didn't work for
53 // MaRTE OS linux_arch
54 // 13-Jul-2007 SANGORRIN substitute calibrate for a new eat that I have added
55 // -----------------------------------------------------------------------
56 #include <stdio.h>
57 #include <stdlib.h>
58 #include <unistd.h>
59 #include <time.h>
60
61 //#include <string.h>
62 //#include <errno.h>
63 //#include <pthread.h>
64 //#include <sched.h>
65 //#include <signal.h>
66 //#include <frsh.h>
67
68 #include "fosa.h"
69 #include "timespec_operations.h"
70
71 #include "marte_non_local_jmp.h"
72
73 /************************/
74 /** Constants and types */
75 /************************/
76
77 #define BUDGET_OVERRUN_SIGNAL SIGRTMIN+3
78 #define RT_ERROR_SIGWAIT -2
79 #define RT_ERROR_TIMER   -3
80
81 typedef struct {
82   fosa_thread_id_t tid;
83   marte_nonlocaljmp_context_t *context_ptr;
84   int dummy;
85 } budget_timer_info_t;
86
87
88 /************************/
89 /** Global Variables    */
90 /************************/
91
92 static marte_nonlocaljmp_context_t context;
93 static int error_status;
94
95
96 /************************/
97 /** Prototypes          */
98 /************************/
99
100 static void * thread_body(void *arg);
101 static void * signal_handler_thread (void * arg);
102
103
104 /************************************************************************/
105 /*                             Main program                             */
106 /************************************************************************/
107
108 int main()
109 {
110     fosa_signal_t set[1];
111     fosa_thread_attr_t attr;
112
113     fosa_thread_id_t tid1, tid2;
114     int terror = 0;
115
116     // set signal mask
117     set[0]=BUDGET_OVERRUN_SIGNAL;
118     if (fosa_set_accepted_signals(set, 1) !=0) {
119       printf ("Error while setting the signal mask\n"); 
120       exit (1);
121     }
122
123     // Create the thread attributes object
124     if (fosa_thread_attr_init (&attr) != 0) {
125       printf("Error while initializing the attributes\n");
126       exit(1);
127     }
128     
129     if (fosa_thread_attr_set_prio (&attr,fosa_get_priority_max()-2) != 0) {
130       printf("Error while setting schedparam\n");
131       exit(1);
132     }
133
134
135     /* create the signal handler thread */
136     terror = fosa_thread_create(&tid1, &attr, signal_handler_thread, NULL);
137     if (terror) {
138         printf("pthread_create signal handler\n");
139         exit(1);
140     }
141
142     // set priority of periodic thread
143     if (fosa_thread_attr_set_prio (&attr,fosa_get_priority_min()+3) != 0) {
144       printf("Error while setting schedparam\n");
145       exit(1);
146     }
147
148     /* create the periodic thread */
149     terror = fosa_thread_create(&tid2, &attr, thread_body, NULL);
150     if (terror) {
151         printf("pthread_create periodic thread\n");
152         exit(1);
153     }
154
155     printf("Main goes to sleep...\n");
156     sleep(20000);
157
158     return 0;
159 }
160
161 // work to be aborted if too long
162 void work() {
163   static int i=0;
164   struct timespec exec_time={1,0}; // 1 second
165
166   i++;
167   printf("start regular code %d\n",i); 
168   // regular code 
169   // eat one second of budget 
170   fosa_eat(&exec_time); 
171   // every five cycles eat an additional one second of budget */
172   if (i%5==0) { 
173     printf("aqui\n");
174     fosa_eat(&exec_time); 
175     printf("aqui tambien\n");
176   } 
177 }
178
179
180
181 /* ------------------------------------------------------------ */
182 /** Body of periodic thread that consumes budget */
183
184 static void * thread_body(void *thread_arg)
185 {
186     struct timespec period={2,500000000}; // 2.5 seconds
187     struct timespec activation_time, old_activation_time;
188     struct timespec budget ={1,400000000}; // 1.4 seconds
189     fosa_timer_id_t timerid;
190     fosa_clock_id_t clockid;
191     budget_timer_info_t timerinfo;
192     fosa_signal_info_t siginfo;
193     int i=0;
194
195     timerinfo.tid=pthread_self();
196     timerinfo.context_ptr=&context;
197
198     fosa_clock_get_time(FOSA_CLOCK_REALTIME,&activation_time);
199
200     if (fosa_thread_get_cputime_clock(timerinfo.tid,&clockid) !=0) {
201       error_status=RT_ERROR_TIMER;
202       pthread_exit ( (void*)&error_status);
203     }
204
205     // create budget timer
206     siginfo.sival_ptr=(void *)(&timerinfo);
207     if (fosa_timer_create (clockid,BUDGET_OVERRUN_SIGNAL,siginfo,&timerid)
208         != 0) 
209       {
210         error_status=RT_ERROR_TIMER;
211         pthread_exit ( (void*)&error_status);
212       }
213
214     printf("Start periodic thread body\n");
215    
216     // main loop
217     while(1) {
218       
219       // set the budget timer
220       if (fosa_timer_arm(timerid, false, &budget) != 0) {
221         error_status=RT_ERROR_TIMER;
222         pthread_exit ( (void*)&error_status);
223       }
224  
225       printf("Begin thread %d,%d\n",(int)activation_time.tv_sec, 
226              (int)(activation_time.tv_nsec/1000000));
227       i++;
228       timerinfo.dummy=i;
229
230       // save context
231       
232       marte_nonlocaljmp_savecontext(&context);
233       printf ("salvado\n");
234
235       if (marte_nonlocaljmp_afterjmp(&context)==0) { 
236         printf("start regular code\n"); 
237         work();
238        } else { 
239         // code executed if asynchronous jump instruction invoked */
240         printf("Aborted thread\n"); 
241       } 
242
243       //printf("after block %d\n",marte_nonlocaljmp_afterjmp(&context));
244       printf("after block\n");
245       fosa_clock_get_time(FOSA_CLOCK_REALTIME,&old_activation_time);
246       decr_timespec(&old_activation_time,&activation_time);
247       printf("End   thread %6.3f\n",old_activation_time.tv_sec+(float)
248              (float)old_activation_time.tv_nsec/1000000000.0);
249       // sleep for a while
250       incr_timespec(&activation_time,&period);
251       clock_nanosleep(FOSA_CLOCK_REALTIME,TIMER_ABSTIME,
252                       &activation_time,&old_activation_time);
253     } // while
254 }
255
256
257 /*----------------------------------------------------------------------*/
258
259 /** Body of signal handler thread 
260  * The signal mask is assumed to be inherited from the parent
261  */
262
263 void * signal_handler_thread (void * arg) {
264
265   fosa_signal_t set[1];
266   fosa_signal_t sig;
267   fosa_signal_info_t siginfo;
268
269   budget_timer_info_t *info;
270
271   // Wait for a budget overrun signal
272   set[0]=BUDGET_OVERRUN_SIGNAL;
273   while (1) {
274     if ((fosa_signal_wait(set, 1, &sig, &siginfo)) == -1) {
275       error_status=RT_ERROR_SIGWAIT;
276       pthread_exit ( (void*)&error_status);
277     }
278     // Restore periodic thread's context
279     printf("About to restore\n");
280     info=((budget_timer_info_t*) (siginfo.sival_ptr));
281     marte_nonlocaljmp_restorecontext(info->tid,info->context_ptr);
282     printf("Restored thread %d\n",info->dummy);
283   }
284 }