X-Git-Url: https://rtime.felk.cvut.cz/gitweb/frescor/fosa.git/blobdiff_plain/29660bd13b283860b273f7c3d310cd6e696efe1d..46da828932c045058077b3d91517e7b29d2a8010:/src_aquosa/fosa_clocks_and_timers.c diff --git a/src_aquosa/fosa_clocks_and_timers.c b/src_aquosa/fosa_clocks_and_timers.c index 6172c0b..9c7e293 100644 --- a/src_aquosa/fosa_clocks_and_timers.c +++ b/src_aquosa/fosa_clocks_and_timers.c @@ -58,28 +58,27 @@ // FOSA(Frescor Operating System Adaptation layer) //================================================ -#include +#include "fosa_clocks_and_timers.h" /************************* * Timing: Clocks *************************/ int fosa_clock_get_time(fosa_clock_id_t clockid, - struct timespec *current_time) + struct timespec *current_time) { return clock_gettime(clockid, current_time); } int fosa_thread_get_cputime_clock(fosa_thread_id_t tid, - fosa_clock_id_t *clockid) + fosa_clock_id_t *clockid) { if (tid.linux_pid == tid.linux_tid) { - /* we're in a standard UNIX process */ + /* standard UNIX process */ *clockid = FOSA_CLOCK_REALTIME; - return 0; } else - /* we're in a thread */ + /* POSIX thread */ return pthread_getcpuclockid(tid.pthread_id, clockid); } @@ -87,58 +86,194 @@ int fosa_thread_get_cputime_clock(fosa_thread_id_t tid, * Timing: Timers *************************/ +/** + * fosa_create_timer() + * + * Create a one-shot timer + * + * This function creates a timer based on the clock specified by clock, + * and associates to this timer a notification mechanism consisting of + * a signal and associated information. Initially, the timer is in the + * disarmed state, i.e., not counting time. It can be armed to start + * counting time with fosa_timer_arm(). + * + * The function stores the identifier of the newly created timer in the + * variable pointed to by timerid. + * + * When the timer expires, the signal number specified by signal will be + * sent together with the information specified by info, to the thread + * that armed the timer (@see fosa_timer_arm()). + * + * Note that, since this is a POSIX implementation, the signal will be sent + * to any thread waiting fot it (in a given UNIX process). + * No signal-waiting thread or similar strategy is implemented, the specific + * thread can be choosed (for example) by means of the signal number. + * + * Returns 0 if successful; otherwise it returns an error code: + * EINVAL: the value of clockid or signal is invalid + * + * EAGAIN: the system lacks enough resources to create the timer + **/ int fosa_timer_create(fosa_clock_id_t clockid, - fosa_signal_t signal, - fosa_signal_info_t info, - fosa_timer_id_t *timerid) + fosa_signal_t signal, + fosa_signal_info_t info, + fosa_timer_id_t *timerid) { struct sigevent event; event.sigev_notify = SIGEV_SIGNAL; event.sigev_signo = signal; - event.sigev_value.sival_int = info.sival_int; + //event.sigev_value.sival_int = info.sival_int; + event.sigev_value = *((union sigval*) &info); return timer_create(clockid, &event, timerid); } -int fosa_timer_delete(fosa_timer_id_t timerid){ - timer_delete(timerid); - return 0; +/** + * fosa_timer_create_with_receiver() + * + * Create a one-shot timer with a specific signal receiver thread + * + * This function creates a timer in the same way as fosa_timer_create, + * except that the signal generated when the timer expires is sent to + * the thread specified by receiver + * + * In this implementation, since in POSIX we can not specify a receiver, + * always returns ENOSYS. + * + * You have to use the "simple" fosa_timer_create. + **/ + int fosa_timer_create_with_receiver(fosa_clock_id_t clockid, + fosa_signal_t signal, + fosa_signal_info_t info, + fosa_timer_id_t *timerid, + fosa_thread_id_t receiver) +{ + /* in POSIX the receiver thread cannot be specified!! */ + //return fosa_timer_create(clockid, signal, info, timerid); + return ENOSYS; +} + + /** + * Delete a timer + * + * The function deletes the timer specified by timerid, which becomes + * unusable. If the timer was armed, it is automatically disarmed before + * deletion. + * + * Returns 0 if successful; otherwise it returns an error code: + * EINVAL: the value of timerid is not valid + **/ +int fosa_timer_delete(fosa_timer_id_t timerid) +{ + return timer_delete(timerid); } +/** + * fosa_timer_arm() + * + * Arm a timer + * + * The timer specified by timer is armed and starts counting time. + * + * If abstime is true, the value pointed to by value is the absolute + * time at which the timer will expire. If value specifies a time instant + * in the past, the timer expires immediately. + * + * If abstime is false, the value pointed to by value is the relative interval + * that must elapse for the timer to expire. + * + * In both cases, absolute or relative, the time is measured with the clock + * associated with the timer when it was created. + * + * If the timer was already armed, the previous time or interval is discarded + * and the timer is rearmed with the new value. + * + * When the timer expires, it is disarmed. + * + * Returns 0 if successful; otherwise it returns an error code: + * EINVAL: the value of timerid or value is invalid + **/ int fosa_timer_arm (fosa_timer_id_t timerid, - bool abstime, - const struct timespec *value) + bool abstime, + const struct timespec *value) { - int flags; struct itimerspec when; - when.it_value = *value; /* one shot timer */ + /* non-periodic one shot timer configuration */ + when.it_value = *value; when.it_interval.tv_sec = 0; - when.it_interval.tv_nsec = 0; /* no periodic behaviour */ - if (abstime) - flags = TIMER_ABSTIME; - else - flags = 0; + when.it_interval.tv_nsec = 0; - return timer_settime(timerid, flags, &when, NULL); + return timer_settime(timerid, + (abstime ? TIMER_ABSTIME : 0), + &when, + NULL); } -int fosa_timer_get_remaining_time(fosa_timer_id_t timerid, struct timespec *remaining_time) +/** + * fosa_timer_get_remaining_time() + * + * Get the remaining time for timer expiration + * + * Returns the relative remaining time for timer expiration. If the + * clock is a CPU clock it returns the time as if the thread was + * executing constantly. + * + * If the timer is disarmed it returns 0. + * + * Returns 0 if successful; otherwise it returns an error code: + * EINVAL: the value of timerid or value is invalid + **/ +int fosa_timer_get_remaining_time(fosa_timer_id_t timerid, + struct timespec *remaining_time) { - errno = EINVAL; - return -1; + int error; + struct itimerspec time; + + if (remaining_time != NULL) { + if ((error = timer_gettime(timerid, &time)) == -1) + return error; + + *remaining_time = time.it_value; + } else + return EINVAL; + + return 0; } -int fosa_timer_disarm(fosa_timer_id_t timerid, struct timespec *remaining_time) +/** + * fosa_timer_disarm() + * + * Disarm a timer + * + * The timer specified by timer is disarmed, and will not expire unless + * it is rearmed. If the timer was already disramed, the function has + * no effect. + * + * If the pointer remaining_time is != NULL, the remaining time before + * expiration will be returned in that pointer. If the timer was + * disarmed a 0 value will be set. + * + * Returns 0 if successful; otherwise it returns an error code: + * EINVAL: the value of timerid or value is invalid + **/ +int fosa_timer_disarm(fosa_timer_id_t timerid, + struct timespec *remaining_time) { - struct itimerspec when; + int error; + struct itimerspec time; + + if (remaining_time != NULL) { + if ((error = timer_gettime(timerid, &time)) == -1) + return error; + + *remaining_time = time.it_value; + } - /* maybe not needed but safer */ - when.it_value.tv_sec = 0; - when.it_value.tv_nsec = 0; - when.it_interval = when.it_value; + time.it_value.tv_sec = 0; + time.it_value.tv_nsec = 0; - return timer_settime(timerid, TIMER_ABSTIME , &when, NULL); + return timer_settime(timerid, 0, &time, NULL); }