]> rtime.felk.cvut.cz Git - frescor/fosa.git/blob - src_marte/fosa_clocks_and_timers.c
03f0b68e2c8d0a685d528fa3648cd6bc08af0b4c
[frescor/fosa.git] / src_marte / fosa_clocks_and_timers.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 FOSA (Frsh Operating System Abstraction)
32 //
33 // FOSA 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.  FOSA 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 FOSA; 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 FOSA header files in a file,
45 // instantiating FOSA generics or templates, or linking other files
46 // with FOSA 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 //fosa_clocks_and_timers.c
53 //==============================================
54 //  ********  ******    ********  **********
55 //  **///// /**    **  **//////  /**     /**
56 //  **      /**    ** /**        /**     /**
57 //  ******* /**    ** /********* /**********
58 //  **////  /**    ** ////////** /**//////**
59 //  **      /**    **        /** /**     /**
60 //  **      /**    **  ********  /**     /**
61 //  //       /******/  ////////   //      //
62 //
63 // FOSA(Frescor Operating System Adaptation layer)
64 //================================================
65
66
67 #include "fosa_clocks_and_timers.h"
68 #include <pthread.h>
69 #include <time.h>
70 #include <stdio.h>
71
72 static const struct timespec zero_time={0,0};
73
74
75 /*************************
76  * Timing: Clocks
77  *************************/
78
79 /**
80  * fosa_get_time()
81  *
82  * Get the time from a clock
83  *
84  * This function sets the variable pointed to by current_time to the
85  * current value of the clock specified by clockid, which may be the
86  * FOSA_CLOCK_REALTIME constant or a value obtained with
87  * fosa_get_cputime_clock()
88  *
89  * Returns 0 if successful; otherwise it returns an error code:
90  *     EINVAL: the value of clockid is invalid
91  *
92  * Alternatively, in case of error the implementation is allowed to
93  * notify it to the system console and then terminate the FRSH
94  * implementation and dependant applications
95  **/
96 int fosa_clock_get_time(fosa_clock_id_t clockid, struct timespec *current_time)
97 {
98   return clock_gettime(clockid,current_time);
99 }
100
101
102 /**
103  * fosa_get_cputime_clock()
104  *
105  * Get the identifier of a cpu-time clock
106  *
107  * This function stores in the variable pointed to by clockid the
108  * identifier of a cpu-time clock for the thread specified by tid.
109  *
110  * Returns 0 if successful; otherwise it returns an error code:
111  *    EINVAL: the value of tid is invalid
112  *
113  * Alternatively, in case of error the implementation is allowed to
114  * notify it to the system console and then terminate the FRSH
115  * implementation and dependant applications
116  **/
117 int fosa_thread_get_cputime_clock
118     (fosa_thread_id_t tid, fosa_clock_id_t *clockid)
119 {
120   return pthread_getcpuclockid(tid,clockid);
121 }
122
123
124 /*************************
125  * Timing: Timers
126  *************************/
127
128 /**
129  * fosa_create_timer()
130  *
131  * Create a one-shot timer
132  *
133  * This function creates a timer based on the clock specified by clock,
134  * and associates to this timer a notification mechanism consisting of
135  * a signal and associated information. Initially, the timer is in the
136  * disarmed state, i.e., not counting time. It can be armed to start
137  * counting time with fosa_timer_arm().
138  *
139  * The function stores the identifier of the newly created timer in the
140  * variable pointed to by timerid.
141  *
142  * When the timer expires, the signal number specified by signal will be
143  * sent together with the information specified by info, to the thread
144  * that armed the timer (@see fosa_timer_arm()).
145  *
146  * In those implementations that do not support queueing a
147  * signal with information to a thread (such as POSIX), the signal may
148  * be sent to any thread that is waiting for this signal via
149  * fosa_signal_wait(). Portability can be ensured by having the receiver
150  * thread be the one who is waiting for the signal.
151  *
152  * Returns 0 if successful; otherwise it returns an error code:
153  *     EINVAL: the value of clockid or signal is invalid
154  *
155  *     EAGAIN: the system lacks enough resources to create the timer
156  *
157  * Alternatively, in case of error the implementation is allowed to
158  * notify it to the system console and then terminate the FRSH
159  * implementation and dependant applications
160  **/
161  int fosa_timer_create
162       (fosa_clock_id_t clockid, fosa_signal_t signal, fosa_signal_info_t info,
163        fosa_timer_id_t *timerid)
164 {
165   struct sigevent evp;
166   evp.sigev_notify=SIGEV_SIGNAL;
167   evp.sigev_signo=signal;
168   evp.sigev_value=* ((union sigval *) &info);
169   // the above casting construct is used to overcome the compiler
170   // restriction that does not allow casts between unions
171   return timer_create(clockid,&evp,timerid);
172 }
173
174 /**
175  * fosa_timer_create_with_receiver()
176  *
177  * Create a one-shot timer with a specific signal receiver thread
178  *
179  * This function creates a timer in the same way as fosa_timer_create,
180  * except that the signal generated when the timer expires is sent to
181  * the thread specified by receiver
182  *
183  * Returns 0 if successful; otherwise it returns an error code:
184  *     FOSA_EINVAL: the value of clockid or signal is invalid
185  *
186  *     FOSA_EAGAIN: the system lacks enough resources to create the timer
187  *
188  * Alternatively, in case of error the implementation is allowed to
189  * notify it to the system console and then terminate the FRSH
190  * implementation and dependant applications
191  **/
192  int fosa_timer_create_with_receiver
193       (fosa_clock_id_t clockid, fosa_signal_t signal, fosa_signal_info_t info,
194        fosa_timer_id_t *timerid, fosa_thread_id_t receiver)
195 {
196   // in POSIX the receiver thread cannot be specified
197   return fosa_timer_create(clockid,signal,info,timerid);
198 }
199
200
201 /**
202  * Delete a timer
203  *
204  * The function deletes the timer specified by timerid, which becomes
205  * unusable. If the timer was armed, it is automatically disarmed before
206  * deletion.
207  *
208  * Returns 0 if successful; otherwise it returns an error code:
209  *     EINVAL: the value of timerid is not valid
210  *
211  * Alternatively, in case of error the implementation is allowed to
212  * notify it to the system console and then terminate the FRSH
213  * implementation and dependant applications
214  **/
215 int fosa_timer_delete(fosa_timer_id_t timerid)
216 {
217   return timer_delete(timerid);
218 }
219
220 /**
221  * fosa_timer_arm()
222  *
223  * Arm a timer
224  *
225  * The timer specified by timer is armed and starts counting time.
226  *
227  * If abstime is true, the value pointed to by value is the absolute
228  * time at which the timer will expire. If value specifies a time instant
229  * in the past, the timer expires immediately.
230  *
231  * If abstime is false, the value pointed to by value is the relative interval
232  * that must elapse for the timer to expire.
233  *
234  * In both cases, absolute or relative, the time is measured with the clock
235  * associated with the timer when it was created.
236  *
237  * If the timer was already armed, the previous time or interval is discarded
238  * and the timer is rearmed with the new value.
239  *
240  * When the timer expires, it is disarmed.
241  *
242  * Returns 0 if successful; otherwise it returns an error code:
243  *    EINVAL: the value of timerid or value is invalid
244  *
245  * Alternatively, in case of error the implementation is allowed to
246  * notify it to the system console and then terminate the FRSH
247  * implementation and dependant applications
248  **/
249 int fosa_timer_arm
250       (fosa_timer_id_t timerid, bool abstime,
251        const struct timespec *value)
252 {
253   int timer_abstime=0;
254   struct itimerspec timer_value;
255
256   // set the abstime flag if necessary
257   if (abstime) {
258     timer_abstime=TIMER_ABSTIME;
259   }
260
261   // set the timer to the specified value, one shot only
262   timer_value.it_value=*value;
263   timer_value.it_interval=zero_time;
264
265   // arm the timer
266   return timer_settime(timerid,timer_abstime,&timer_value,NULL);
267 }
268
269 /**
270  * fosa_timer_get_remaining_time()
271  *
272  * Get the remaining time for timer expiration
273  *
274  * Returns the relative remaining time for timer expiration.  If the
275  * clock is a CPU clock it returns the time as if the thread was
276  * executing constantly.
277  *
278  * If the timer is disarmed it returns 0.
279  *
280  * Returns 0 if successful; otherwise it returns an error code:
281  *    EINVAL: the value of timerid or value is invalid
282  *
283  * Alternatively, in case of error the implementation is allowed to
284  * notify it to the system console and then terminate the FRSH
285  * implementation and dependant applications
286  **/
287 int fosa_timer_get_remaining_time
288         (fosa_timer_id_t timerid, struct timespec *remaining_time)
289 {
290     struct itimerspec timer_value;
291     int error_code;
292
293     if (remaining_time!=NULL) {
294         error_code=timer_gettime(timerid,&timer_value);
295         if (error_code==-1) return errno;
296         *remaining_time=timer_value.it_value;
297     } else {
298         return EINVAL;
299     }
300     return 0;
301 }
302
303 /**
304  * fosa_timer_disarm()
305  *
306  * Disarm a timer
307  *
308  * The timer specified by timer is disarmed, and will not expire unless
309  * it is rearmed. If the timer was already disramed, the function has
310  * no effect.
311  *
312  * If the pointer remaining_time is != NULL, the remaining time before
313  * expiration will be returned in that pointer.  If the timer was
314  * disarmed a 0 value will be set.
315  *
316  * Returns 0 if successful; otherwise it returns an error code:
317  *    EINVAL: the value of timerid or value is invalid
318  *
319  * Alternatively, in case of error the implementation is allowed to
320  * notify it to the system console and then terminate the FRSH
321  * implementation and dependant applications
322  **/
323 int fosa_timer_disarm
324    (fosa_timer_id_t timerid,
325     struct timespec *remaining_time)
326 {
327   struct itimerspec timer_value;
328   int error_code;
329
330   if (remaining_time!=NULL) {
331     error_code=timer_gettime(timerid,&timer_value);
332     if (error_code==-1) return errno;
333     *remaining_time=timer_value.it_value;
334   }
335   timer_value.it_value=zero_time;
336   timer_value.it_interval=zero_time;
337   return timer_settime(timerid,0,&timer_value,NULL);
338 }