1 // -----------------------------------------------------------------------
2 // Copyright (C) 2006 - 2009 FRESCOR consortium partners:
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
11 // Thales Communication S.A. FRANCE
12 // Visual Tools S.A. SPAIN
13 // Rapita Systems Ltd UK
16 // See http://www.frescor.org for a link to partners' websites
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
24 // based on previous work (FSF) done in the FIRST project
26 // Copyright (C) 2005 Mälardalen University, SWEDEN
27 // Scuola Superiore S.Anna, ITALY
28 // Universidad de Cantabria, SPAIN
29 // University of York, UK
31 // FSF API web pages: http://marte.unican.es/fsf/docs
32 // http://shark.sssup.it/contrib/first/docs/
34 // This file is part of FOSA (Frsh Operating System Adaption)
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.
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 // -----------------------------------------------------------------------
56 //==============================================
57 // ******** ****** ******** **********
58 // **///// /** ** **////// /** /**
59 // ** /** ** /** /** /**
60 // ******* /** ** /********* /**********
61 // **//// /** ** ////////** /**//////**
62 // ** /** ** /** /** /**
63 // ** /** ** ******** /** /**
64 // // /******/ //////// // //
66 // FOSA(Frescor Operating System Adaptation layer)
67 //================================================
69 #include "fosa_time.h"
70 #include "fosa_clocks_and_timers.h"
72 static const struct timespec zero_time={0,0};
75 /*************************
77 *************************/
80 * fosa_clock_get_time()
82 * Get the time from a clock
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()
89 * Returns 0 if successful; otherwise it returns an error code:
90 * EINVAL: the value of clockid is invalid
92 int fosa_clock_get_time(fosa_clock_id_t clockid,
93 fosa_abs_time_t *current_time)
96 struct timespec current_time_tspec;
98 ret = clock_gettime(clockid, ¤t_time_tspec);
99 if (ret) return errno;
101 *current_time = fosa_timespec_to_abs_time(current_time_tspec);
107 * fosa_get_cputime_clock()
109 * Get the identifier of a cpu-time clock
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.
114 * Returns 0 if successful; otherwise it returns an error code:
115 * EINVAL: the value of tid is invalid
117 int fosa_thread_get_cputime_clock(fosa_thread_id_t tid,
118 fosa_clock_id_t *clockid)
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);
127 return ret ? errno : 0;
130 /*************************
132 *************************/
135 * fosa_create_timer()
137 * Create a one-shot timer
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().
145 * The function stores the identifier of the newly created timer in the
146 * variable pointed to by timerid.
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()).
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.
157 * Returns 0 if successful; otherwise it returns an error code:
158 * EINVAL: the value of clockid or signal is invalid
160 * EAGAIN: the system lacks enough resources to create the timer
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)
168 struct sigevent event;
170 event.sigev_notify = SIGEV_SIGNAL;
171 event.sigev_signo = signal;
172 event.sigev_value = *((union sigval*) &info);
174 ret = timer_create(clockid, &event, timerid);
176 return ret ? errno : 0;
180 * fosa_timer_create_with_receiver()
182 * Create a one-shot timer with a specific signal receiver thread
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
188 * You have to use the "simple" fosa_timer_create.
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)
197 struct sigevent event;
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;
205 ret = timer_create(clockid, &event, timerid);
207 return ret ? errno : 0;
213 * The function deletes the timer specified by timerid, which becomes
214 * unusable. If the timer was armed, it is automatically disarmed before
217 * Returns 0 if successful; otherwise it returns an error code:
218 * EINVAL: the value of timerid is not valid
220 int fosa_timer_delete(fosa_timer_id_t timerid)
224 ret = timer_delete(timerid);
226 return ret ? errno : 0;
230 * fosa_rel_timer_arm()
232 * Arm a timer with a relative time interval
234 * The timer specified by timer is armed and starts counting time.
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.
240 * The time is measured with the clock associated with the timer when
243 * If the timer was already armed, the previous time or interval is discarded
244 * and the timer is rearmed with the new value.
246 * When the timer expires, it is disarmed.
248 * Returns 0 if successful; otherwise it returns an error code:
249 * FOSA_EINVAL: the value of timerid or value is invalid
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
255 int fosa_rel_timer_arm(fosa_timer_id_t timerid, const fosa_rel_time_t *value)
258 struct itimerspec when;
260 /* non-periodic one shot timer */
261 when.it_value = fosa_abs_time_to_timespec(*value);
262 when.it_interval = zero_time;
264 ret = timer_settime(timerid, 0, &when, NULL);
266 return ret ? errno : 0;
271 * fosa_abs_timer_arm()
273 * Arm a timer that will expire in an absolute time instant.
275 * The timer specified by timer is armed and starts counting time.
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.
281 * The time is measured with the clock associated with the timer when
284 * If the timer was already armed, the previous time or interval is discarded
285 * and the timer is rearmed with the new value.
287 * When the timer expires, it is disarmed.
289 * Returns 0 if successful; otherwise it returns an error code:
290 * FOSA_EINVAL: the value of timerid or value is invalid
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
296 int fosa_abs_timer_arm(fosa_timer_id_t timerid, const fosa_abs_time_t *value)
299 struct itimerspec when;
301 /* non-periodic one shot timer */
302 when.it_value = fosa_abs_time_to_timespec(*value);
303 when.it_interval = zero_time;
305 ret = timer_settime(timerid, TIMER_ABSTIME, &when, NULL);
307 return ret ? errno : 0;
311 * fosa_timer_get_remaining_time()
313 * Get the remaining time for timer expiration
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.
319 * If the timer is disarmed it returns 0.
321 * Returns 0 if successful; otherwise it returns an error code:
322 * EINVAL: the value of timerid or value is invalid
324 int fosa_timer_get_remaining_time(fosa_timer_id_t timerid,
325 fosa_rel_time_t *remaining_time)
328 struct itimerspec time;
333 ret = timer_gettime(timerid, &time);
334 *remaining_time = fosa_timespec_to_rel_time(time.it_value);
336 return ret ? errno : 0;
340 * fosa_timer_disarm()
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
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.
352 * Returns 0 if successful; otherwise it returns an error code:
353 * EINVAL: the value of timerid or value is invalid
355 int fosa_timer_disarm(fosa_timer_id_t timerid,
356 struct timespec *remaining_time)
359 struct itimerspec time;
364 ret = timer_gettime(timerid, &time);
365 if (ret) return errno;
367 *remaining_time = fosa_timespec_to_rel_time(time.it_value);
369 time.it_value = zero_time;
370 time.it_interval = zero_time;
372 ret = timer_settime(timerid, 0, &time, NULL);
374 return ret ? errno : 0;