]> rtime.felk.cvut.cz Git - frescor/fosa.git/blob - src_aquosa/fosa_clocks_and_timers.c
Makefile: Add missing header file
[frescor/fosa.git] / src_aquosa / fosa_clocks_and_timers.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 //
56 //==============================================
57 //  ********  ******    ********  **********
58 //  **///// /**    **  **//////  /**     /**
59 //  **      /**    ** /**        /**     /**
60 //  ******* /**    ** /********* /**********
61 //  **////  /**    ** ////////** /**//////**
62 //  **      /**    **        /** /**     /**
63 //  **      /**    **  ********  /**     /**
64 //  //       /******/  ////////   //      // 
65 //
66 // FOSA(Frescor Operating System Adaptation layer)
67 //================================================
68
69 #include "fosa_time.h"
70 #include "fosa_clocks_and_timers.h"
71
72 static const struct timespec zero_time={0,0};
73
74
75 /*************************
76  * Timing: Clocks
77  *************************/
78
79 /**
80  * fosa_clock_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 int fosa_clock_get_time(fosa_clock_id_t clockid,
93                         fosa_abs_time_t *current_time)
94 {
95         int ret;
96         struct timespec current_time_tspec;
97
98         ret = clock_gettime(clockid, &current_time_tspec);
99         if (ret) return errno;
100
101         *current_time = fosa_timespec_to_abs_time(current_time_tspec);
102
103         return 0;
104 }
105
106 /**
107  * fosa_get_cputime_clock()
108  *
109  * Get the identifier of a cpu-time clock
110  *
111  * This function stores in the variable pointed to by clockid the
112  * identifier of a cpu-time clock for the thread specified by tid.
113  *
114  * Returns 0 if successful; otherwise it returns an error code:
115  *    EINVAL: the value of tid is invalid
116  **/
117 int fosa_thread_get_cputime_clock(fosa_thread_id_t tid,
118                                   fosa_clock_id_t *clockid)
119 {
120         int ret;
121
122         if (tid.linux_pid == tid.linux_tid) /* standard UNIX process */
123                 ret = clock_getcpuclockid(tid.linux_pid, clockid);
124         else /* POSIX thread */
125                 ret = pthread_getcpuclockid(tid.pthread_id, clockid);
126
127         return ret ? errno : 0;
128 }
129
130 /*************************
131  * Timing: Timers
132  *************************/
133
134 /**
135  * fosa_create_timer()
136  *
137  * Create a one-shot timer
138  *
139  * This function creates a timer based on the clock specified by clock,
140  * and associates to this timer a notification mechanism consisting of
141  * a signal and associated information. Initially, the timer is in the
142  * disarmed state, i.e., not counting time. It can be armed to start
143  * counting time with fosa_timer_arm().
144  *
145  * The function stores the identifier of the newly created timer in the
146  * variable pointed to by timerid.
147  *
148  * When the timer expires, the signal number specified by signal will be
149  * sent together with the information specified by info, to the thread
150  * that armed the timer (@see fosa_timer_arm()).
151  *
152  * Note that, since this is a POSIX implementation, the signal will be sent
153  * to any thread waiting fot it (in a given UNIX process).
154  * No signal-waiting thread or similar strategy is implemented, the specific
155  * thread can be choosed (for example) by means of the signal number.
156  *
157  * Returns 0 if successful; otherwise it returns an error code:
158  *     EINVAL: the value of clockid or signal is invalid
159  *
160  *     EAGAIN: the system lacks enough resources to create the timer
161  **/
162 int fosa_timer_create(fosa_clock_id_t clockid,
163                       fosa_signal_t signal,
164                       fosa_signal_info_t info,
165                       fosa_timer_id_t *timerid)
166 {
167         int ret;
168         struct sigevent event;
169
170         event.sigev_notify = SIGEV_SIGNAL;
171         event.sigev_signo = signal;
172         event.sigev_value = *((union sigval*) &info);
173
174         ret = timer_create(clockid, &event, timerid);
175
176         return ret ? errno : 0;
177 }
178
179 /**
180  * fosa_timer_create_with_receiver()
181  *
182  * Create a one-shot timer with a specific signal receiver thread
183  *
184  * This function creates a timer in the same way as fosa_timer_create,
185  * except that the signal generated when the timer expires is sent to
186  * the thread specified by receiver
187  * 
188  * You have to use the "simple" fosa_timer_create. 
189  **/
190  int fosa_timer_create_with_receiver(fosa_clock_id_t clockid,
191                                      fosa_signal_t signal,
192                                      fosa_signal_info_t info,
193                                      fosa_timer_id_t *timerid,
194                                      fosa_thread_id_t receiver)
195 {
196         int ret;
197         struct sigevent event;
198
199         event.sigev_notify = SIGEV_SIGNAL;
200         event.sigev_signo = signal;
201         event.sigev_value = *((union sigval*) &info);
202         event.sigev_notify = SIGEV_THREAD_ID | SIGEV_SIGNAL;
203         event._sigev_un._tid = receiver.linux_tid;
204
205         ret = timer_create(clockid, &event, timerid);
206
207         return ret ? errno : 0;
208 }
209
210 /**
211  * Delete a timer
212  *
213  * The function deletes the timer specified by timerid, which becomes
214  * unusable. If the timer was armed, it is automatically disarmed before
215  * deletion.
216  *
217  * Returns 0 if successful; otherwise it returns an error code:
218  *     EINVAL: the value of timerid is not valid
219  **/
220 int fosa_timer_delete(fosa_timer_id_t timerid)
221 {
222         int ret;
223
224         ret = timer_delete(timerid);
225
226         return ret ? errno : 0;
227 }
228
229 /**
230  * fosa_rel_timer_arm()
231  *
232  * Arm a timer with a relative time interval
233  *
234  * The timer specified by timer is armed and starts counting time.
235  *
236  * The value pointed to by value is the relative interval that must
237  * elapse for the timer to expire.  Negative values cause the timer to
238  * expire immediately.
239  *
240  * The time is measured with the clock associated with the timer when
241  * it was created. 
242  *
243  * If the timer was already armed, the previous time or interval is discarded
244  * and the timer is rearmed with the new value.
245  *
246  * When the timer expires, it is disarmed.
247  *
248  * Returns 0 if successful; otherwise it returns an error code:
249  *    FOSA_EINVAL: the value of timerid or value is invalid
250  *
251  * Alternatively, in case of error the implementation is allowed to
252  * notify it to the system console and then terminate the FRSH
253  * implementation and dependant applications
254  **/
255 int fosa_rel_timer_arm(fosa_timer_id_t timerid, const fosa_rel_time_t *value)
256 {
257         int ret;
258         struct itimerspec when;
259
260         /* non-periodic one shot timer */
261         when.it_value = fosa_abs_time_to_timespec(*value);
262         when.it_interval = zero_time;
263
264         ret = timer_settime(timerid, 0, &when, NULL);
265
266         return ret ? errno : 0;
267 }
268
269
270 /**
271  * fosa_abs_timer_arm()
272  *
273  * Arm a timer that will expire in an absolute time instant.
274  *
275  * The timer specified by timer is armed and starts counting time.
276  *
277  * The value pointed to by value is the absolute time at which the
278  * timer will expire. If value specifies a time instant in the past,
279  * the timer expires immediately. 
280  *
281  * The time is measured with the clock associated with the timer when
282  * it was created. 
283  *
284  * If the timer was already armed, the previous time or interval is discarded
285  * and the timer is rearmed with the new value.
286  *
287  * When the timer expires, it is disarmed.
288  *
289  * Returns 0 if successful; otherwise it returns an error code:
290  *    FOSA_EINVAL: the value of timerid or value is invalid
291  *
292  * Alternatively, in case of error the implementation is allowed to
293  * notify it to the system console and then terminate the FRSH
294  * implementation and dependant applications
295  **/
296 int fosa_abs_timer_arm(fosa_timer_id_t timerid, const fosa_abs_time_t *value)
297 {
298         int ret;
299         struct itimerspec when;
300
301         /* non-periodic one shot timer */
302         when.it_value = fosa_abs_time_to_timespec(*value);
303         when.it_interval = zero_time;
304
305         ret = timer_settime(timerid, TIMER_ABSTIME, &when, NULL);
306
307         return ret ? errno : 0;
308 }
309
310 /**
311  * fosa_timer_get_remaining_time()
312  *
313  * Get the remaining time for timer expiration
314  *
315  * Returns the relative remaining time for timer expiration.  If the
316  * clock is a CPU clock it returns the time as if the thread was
317  * executing constantly.
318  *
319  * If the timer is disarmed it returns 0.
320  *
321  * Returns 0 if successful; otherwise it returns an error code:
322  *    EINVAL: the value of timerid or value is invalid
323  **/
324 int fosa_timer_get_remaining_time(fosa_timer_id_t timerid,
325                                   fosa_rel_time_t *remaining_time)
326 {
327         int ret;
328         struct itimerspec time;
329
330         if (!remaining_time)
331                 return FOSA_EINVAL;
332
333         ret = timer_gettime(timerid, &time);
334         *remaining_time = fosa_timespec_to_rel_time(time.it_value);
335
336         return ret ? errno : 0;
337 }
338
339 /**
340  * fosa_timer_disarm()
341  *
342  * Disarm a timer
343  *
344  * The timer specified by timer is disarmed, and will not expire unless
345  * it is rearmed. If the timer was already disramed, the function has
346  * no effect.
347  *
348  * If the pointer remaining_time is != NULL, the remaining time before
349  * expiration will be returned in that pointer.  If the timer was
350  * disarmed a 0 value will be set.
351  *
352  * Returns 0 if successful; otherwise it returns an error code:
353  *    EINVAL: the value of timerid or value is invalid
354  **/
355 int fosa_timer_disarm(fosa_timer_id_t timerid,
356                       struct timespec *remaining_time)
357 {
358         int ret;
359         struct itimerspec time;
360
361         if (!remaining_time)
362                 return FOSA_EINVAL;
363
364         ret = timer_gettime(timerid, &time);
365         if (ret) return errno;
366
367         *remaining_time = fosa_timespec_to_rel_time(time.it_value);
368
369         time.it_value = zero_time;
370         time.it_interval = zero_time;
371
372         ret = timer_settime(timerid, 0, &time, NULL);
373
374         return ret ? errno : 0;
375 }
376