]> rtime.felk.cvut.cz Git - ert_linux.git/blob - ert_linux/ert_linux_main.tlc
Add mlockall() to the generated code
[ert_linux.git] / ert_linux / ert_linux_main.tlc
1 %%
2 %%
3 %% description:
4 %%  This TLC script generates ert_main.c
5 %%  case.
6 %%
7 %% authors: Michal Sojka <sojkam1@fel.cvut.cz>
8 %%          Lukas Hamacek <hamacl1@fel.cvut.cz>
9 %%
10 %% Department of Control Engineering
11 %% Faculty of Electrical Engineering
12 %% Czech Technical University in Prague
13 %%
14
15 %% GENERATEDECLARATIONS
16 %%  This function generates main function declarations.
17 %%
18
19 %assign ::tid01Eq = LibGetTID01EQ()
20
21 %function generateDeclarations() Output
22
23   /* Multirate - Multitasking case main file */
24   #define _BSD_SOURCE                    /* For usleep() */
25   #define _POSIX_C_SOURCE 200112L        /* For clock_gettime() & clock_nanosleep() */
26   #include <stdio.h>                     /* This ert_main.c example uses printf/fflush */
27   #include <pthread.h>                   /* Thread library header file */
28   #include <sched.h>                     /* OS scheduler header file */
29   #include <semaphore.h>                 /* Semaphores library header file */
30   #include <time.h>
31   #include <stdlib.h>
32   #include <unistd.h>
33   #include <sys/mman.h>                  /* For mlockall() */
34   #include "%<modelName>.h"              /* Model's header file */
35   #include "rtwtypes.h"                  /* MathWorks types */
36   %if extMode == 1
37     #include "ext_work.h"                  /* External mode header file */
38   %endif
39
40   /*==================*
41    * Required defines *
42    *==================*/
43
44   #ifndef MODEL
45   # error Must specify a model name.  Define MODEL=name.
46   #else
47   /* create generic macros that work with any model */
48   # define EXPAND_CONCAT(name1,name2) name1 ## name2
49   # define CONCAT(name1,name2) EXPAND_CONCAT(name1,name2)
50   # define MODEL_INITIALIZE CONCAT(MODEL,_initialize)
51   # define MODEL_STEP       CONCAT(MODEL,_step)
52   # define MODEL_TERMINATE  CONCAT(MODEL,_terminate)
53   # define RT_MDL           CONCAT(MODEL,_M)
54   #endif
55
56   /* Error checking */
57   #define STRINGIZE(num) #num
58   #define POS(line) __FILE__ ":" STRINGIZE(line)
59   #define CHECK0(expr) do { int __err = (expr); if (__err) { fprintf(stderr, "Error: %s returned '%s' at " POS(__LINE__) "\n", #expr, strerror(__err)); exit(1); } } while (0);
60   #define CHECKE(expr) do { if ((expr) == -1) { perror(#expr " at " POS(__LINE__)); exit(1); } } while (0);
61
62   /**
63    * Maximal priority used by base rate thread.
64    */
65   #define MAX_PRIO (sched_get_priority_min(SCHED_FIFO) + %<numSampleTimes>)
66
67   /**
68    * Thread handle of the base rate thread.
69    * Fundamental sample time = %<fundamentalStepSize>s
70    */
71   pthread_t base_rate_thread;
72
73   /**
74    * Thread handles of and semaphores for sub rate threads. The array
75    * is indexed by TID, i.e. the first one or two elements are unused.
76   %foreach i = numSampleTimes
77       %if i == 0 || i == 1 && tid01Eq
78       %continue
79     %endif
80     %assign s = sampleTime%<i>
81     %assign o = offset%<i>
82    * TID%<i>: sample time = %<s>s, offset = %<o>s
83   %endforeach
84    */
85   struct sub_rate {
86   pthread_t thread;
87   sem_t     sem;
88   } sub_rate[%<numSampleTimes>];
89
90   /**
91    * Flag if the simulation has been terminated.
92    */
93   int simulationFinished = 0;
94
95   %if extMode == 1
96     /* Indication that the base rate thread has started */
97     sem_t ext_mode_ready;
98   %endif
99 %endfunction
100
101 %function printfunc() Output
102   /% printf("%s\n", __func__); %/
103 %endfunction
104
105 %function generateRtOneStep() Output
106   %foreach j = numSampleTimes - 1
107     %assign i = j + 1
108     %if i == 1 && tid01Eq
109       %continue
110     %endif
111     void *sub_rate%<i>(void *arg)
112     {
113       while(!simulationFinished) {
114         sem_wait(&sub_rate[%<i>].sem);    /* sem_val = 1 */
115         %<printfunc()>
116         %<modelName>_step%<i>();
117         sem_wait(&sub_rate[%<i>].sem);    /* sem_val = 0 */
118       }
119     }
120   %endforeach
121 %endfunction
122
123
124 %% GENERATEMAIN
125 %%  This function generates code of the main function function.
126 %%
127 %function generateMain() Output
128   /**
129    * This is the thread function of the base rate loop.
130    * Fundamental sample time = %<fundamentalStepSize>s
131    */
132   void * base_rate()
133   {
134     %assign  sec = FEVAL("uint32", fundamentalStepSize)
135     %assign nsec = FEVAL("uint32", (fundamentalStepSize - FEVAL("floor", fundamentalStepSize))*1000000000)
136     struct timespec now, next;
137     struct timespec period = { %<sec>, %<nsec> }; /* %<fundamentalStepSize> seconds */
138     boolean_T eventFlags[%<numSampleTimes>];             /* Model has %<numSampleTimes> rates */
139     int_T taskCounter[%<numSampleTimes>] = %<FcnInitializeTaskCounter()>;
140     int_T OverrunFlags[%<numSampleTimes>];
141     int step_sem_value;
142     int_T i;
143
144     %if extMode == 1
145       %<SLibGenERTExtModeInit()>
146       CHECKE(sem_post(&ext_mode_ready));
147     %endif
148
149     clock_gettime(CLOCK_MONOTONIC, &next);
150
151     /* Main loop, running until all the threads are terminated */
152     while(rtmGetErrorStatus(%<modelName>_M) == NULL && !rtmGetStopRequested(%<modelName>_M)) {
153       %<printfunc()>
154       /* Check subrate overrun, set rates that need to run this time step*/
155       %<LibCallSetEventForThisBaseStep("eventFlags")>\
156
157       /* Trigger sub-rate threads */
158       %foreach i = numSampleTimes
159         %if i == 0 || i == 1 && tid01Eq
160           %continue
161         %endif
162         %assign s = sampleTime%<i>
163         %assign o = offset%<i>
164         /* Sampling rate %<i>, sample time = %<s>, offset = %<o> */
165         if (eventFlags[%<i>]) {
166           eventFlags[%<i>] = FALSE;
167           sem_getvalue(&sub_rate[%<i>].sem, &step_sem_value);
168           if (step_sem_value) {
169             rtmSetErrorStatus(%<modelName>_M, "Overrun");
170             printf("Sub rate %<i> overrun, sample time=%<s>s, offset=%<o>s is too fast\n");
171             break;
172           }
173           sem_post(&sub_rate[%<i>].sem);
174           sem_post(&sub_rate[%<i>].sem);
175         }
176       %endforeach
177
178       /* Execute base rate step */
179       %if solverMode == "SingleTasking"
180         %<modelName>_step();
181       %else
182         %<modelName>_step0();
183       %endif
184
185       %if extMode == 1
186         rtExtModeCheckEndTrigger();
187       %endif
188
189       do {
190         next.tv_sec += period.tv_sec;
191         next.tv_nsec += period.tv_nsec;
192         if (next.tv_nsec >= 1000000000) {
193           next.tv_sec++;
194           next.tv_nsec -= 1000000000;
195         }
196         clock_gettime(CLOCK_MONOTONIC, &now);
197         if (now.tv_sec > next.tv_sec ||
198             (now.tv_sec == next.tv_sec && now.tv_nsec > next.tv_nsec)) {
199           uint32_T usec = (now.tv_sec - next.tv_sec) * 1000000 + (now.tv_nsec - next.tv_nsec)/1000;
200           fprintf(stderr, "Base rate (%<fundamentalStepSize>s) overrun by %d us\n", usec);
201           next = now;
202           continue;
203         }
204       } while (0);
205       clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &next, NULL);
206
207     }
208
209     simulationFinished = 1;
210     /* Final step */
211     for (i = %<1 + tid01Eq>; i < %<numSampleTimes>; i++) {
212       sem_post(&sub_rate[i].sem);
213       sem_post(&sub_rate[i].sem);
214     }
215   }
216
217   /**
218    * This is the main function of the model.
219    * Multirate - Multitasking case main file
220    */
221   int_T main(int_T argc, const char_T *argv[])
222   {
223     const char_T *errStatus;
224     int_T i;
225     pthread_attr_t attr;
226     struct sched_param sched_param;
227
228     %if extMode == 1
229       /* External mode */
230       /* rtERTExtModeParseArgs(argc, argv); */
231       rtExtModeParseArgs(argc, argv, NULL);
232       CHECKE(sem_init(&ext_mode_ready, 0, 0));
233     %else
234       (void)(argc);
235       (void *)(argv);
236     %endif
237
238     CHECKE(mlockall(MCL_FUTURE));
239
240     /* Initialize model */
241     %<modelName>_initialize();
242     simulationFinished = 0;
243
244     /* Prepare task attributes */
245     CHECK0(pthread_attr_init(&attr));
246     CHECK0(pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED));
247     CHECK0(pthread_attr_setschedpolicy(&attr, SCHED_FIFO));
248
249     %foreach i = numSampleTimes
250       %if i == 0 || i == 1 && tid01Eq
251         %continue
252       %endif
253       %assign s = sampleTime%<i>
254       %assign o = offset%<i>
255
256       /* Initializing the step semaphore of the loop %<i> */
257       CHECKE(sem_init(&sub_rate[%<i>].sem, 0, 0));
258
259       /* Starting loop %<i> thread for sample time = %<s>s, offset = %<o>s. */
260       sched_param.sched_priority = MAX_PRIO - %<i>;
261       CHECK0(pthread_attr_setschedparam(&attr, &sched_param));
262       CHECK0(pthread_create(&sub_rate[%<i>].thread, &attr, sub_rate%<i>, (void*)%<i>));
263
264     %endforeach
265
266     /* Starting the base rate thread */
267     sched_param.sched_priority = MAX_PRIO;
268     CHECK0(pthread_attr_setschedparam(&attr, &sched_param));
269     CHECK0(pthread_create(&base_rate_thread, &attr, base_rate, NULL));
270     CHECK0(pthread_attr_destroy(&attr));
271
272     %if extMode == 1
273       /* External mode */
274       CHECKE(sem_wait(&ext_mode_ready));
275       while(rtmGetErrorStatus(%<modelName>_M) == NULL && !rtmGetStopRequested(%<modelName>_M)) {
276         rtExtModeOneStep(rtmGetRTWExtModeInfo(RT_MDL), NUMST, (boolean_T *)&rtmGetStopRequested(RT_MDL));
277         usleep(%<FEVAL("uint32", fundamentalStepSize * 1000000)>);
278       }
279     %endif
280
281     /* Wait for threads to finish */
282     pthread_join(base_rate_thread, NULL);
283     %foreach i = numSampleTimes
284       %if i == 0 || i == 1 && tid01Eq
285         %continue
286       %endif
287       pthread_join(sub_rate[%<i>].thread, NULL);
288     %endforeach
289
290     %if extMode == 1
291       rtExtModeShutdown(%<numSampleTimes>);
292     %endif
293
294     /* Terminate model */
295     %<modelName>_terminate();
296
297     errStatus = rtmGetErrorStatus(%<modelName>_M);
298     if(errStatus != NULL && strcmp(errStatus, "Simulation finished")) {
299       %%printf("%s\n", rtmGetErrorStatus(%<modelName>_M));
300       if(!strcmp(errStatus, "Overrun")) {
301         printf("ISR overrun - sampling rate too fast\n");
302       }
303       return(1);
304     }
305     return 0;
306   }
307
308 /* Local Variables: */
309 /* compile-command: "make -f %<modelName>.mk" */
310 /* End: */
311
312 %endfunction