]> rtime.felk.cvut.cz Git - frescor/fosa.git/commitdiff
Keep the FOSA implementation for the AQuoSA platform in touch
authorfaggioli <faggioli@35b4ef3e-fd22-0410-ab77-dab3279adceb>
Thu, 27 Mar 2008 12:41:03 +0000 (12:41 +0000)
committerfaggioli <faggioli@35b4ef3e-fd22-0410-ab77-dab3279adceb>
Thu, 27 Mar 2008 12:41:03 +0000 (12:41 +0000)
with the phase-II of the project.

git-svn-id: http://www.frescor.org/private/svn/frescor/fosa/trunk@1049 35b4ef3e-fd22-0410-ab77-dab3279adceb

src_aquosa/Makefile
src_aquosa/fosa_clocks_and_timers.c
src_aquosa/fosa_mutexes_and_condvars.c
src_aquosa/fosa_threads_and_signals.c
src_aquosa/fosa_time.c [new file with mode: 0644]
src_aquosa/frsh_fosa.c [deleted file]

index f9adaab59b474a79fa9a639e5ec1f4f1a6300ab6..0e4f352b4c028e6fb81f25313bb043ea10fcec6e 100644 (file)
@@ -40,7 +40,7 @@ OBJOPT += -fPIC
 STATIC_NAME = libfosa_qres.a
 SHARED_NAME = libfosa_qres.so
 
-SRC = fosa_clocks_and_timers.c fosa_threads_and_signals.c fosa_mutexes_and_condvars.c
+SRC = fosa_clocks_and_timers.c fosa_threads_and_signals.c fosa_mutexes_and_condvars.c fosa_time.c
 
 PUBLIC_H_FOSA = fosa_app_def_sched.h fosa.h fosa_opaque_types.h fosa_clocks_and_timers.h \
                fosa_configuration_parameters.h fosa_mutexes_and_condvars.h fosa_threads_and_signals.h \
@@ -65,7 +65,7 @@ all: ../lib/$(STATIC_NAME) ../lib/$(SHARED_NAME)
 
 ../lib/$(SHARED_NAME): $(OBJS)
        @exec echo -n "=> Generating libfosa_qres.so: ";
-       $(CC) -shared -o $@ $(OBJS)
+       @$(CC) -shared -o $@ $(OBJS)
        @exec echo "  [OK]"
 
 
@@ -75,8 +75,8 @@ all: ../lib/$(STATIC_NAME) ../lib/$(SHARED_NAME)
 ###############################################################
 
 %.o: %.c $(PUBLIC_H_FILE_LOCATIONS) $(PRIVATE_H)
-       @exec echo -n "=> Compiling $<: ";
-       $(CC) $(CFLAGS) -c $< 
+       @@exec echo -n "=> Compiling $<: ";
+       @$(CC) $(CFLAGS) -c $<
        @exec echo "  [OK]"
 
 # Clean up #
index 6172c0bc5ccddb68ce2509cfed6f4bfadeb4ed2b..9c7e2930cda6e9cf384f21b41baad35610b746da 100644 (file)
 // FOSA(Frescor Operating System Adaptation layer)
 //================================================
 
-#include <fosa.h>
+#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);
 }
 
index 05ac5e64b7f1ca97cd36b3c74a6c67591b6f7871..c40e85633f3218728d10677b223c99b203b68311 100644 (file)
 // FOSA(Frescor Operating System Adaptation layer)
 //================================================
 
-#include <fosa.h>
-
+#include "fosa_mutexes_and_condvars.h"
 
 /*******************************************************
  * Mutexes with priority/bandwidth inheritance
  ******************************************************/
 
-
+/**
+ * fosa_mutex_init()
+ *
+ * Initialize a frsh mutex
+ *
+ * The mutex pointed to by mutex is initialized as a mutex using
+ * the priority ceiling protocol. A priority ceiling of prioceiling
+ * is assigned to this mutex.
+ *
+ * Returns 0 if successful; otherwise it returns an error code:
+ *    EINVAL: the value of prioceiling is invalid
+ *    EAGAIN: the system lacked the necessary resources to create the mutex
+ *    ENOMEM: Insufficient memory exists to initialize the mutex
+ *    EBUSY:  The system has detected an attempt to reinitialize the mutex
+ **/
 int fosa_mutex_init(fosa_mutex_t *mutex, int prioceiling)
 {
-       //pthread_mutexattr_t mutex_attr;
-
-       /* prioceiling serves as a flag */
-       /* if (prioceiling) {
-                       pthread_mutexattr_init(&mutex_attr);
-               pthread_mutexattr_setprotocol(&mutex_attr, PTHREAD_PRIO_INHERIT);
-               
-               return pthread_mutex_init(mutex, &mutex_attr);
-       } else */
-               return pthread_mutex_init(mutex, NULL);
+       int error;
+       pthread_mutexattr_t attr;
+
+       if ((error = pthread_mutexattr_init(&attr)) != 0)
+               return error;
+
+       if ((error = pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_INHERIT)) != 0)
+               return error;
+
+       return pthread_mutex_init(mutex, &attr);
 }
 
+/**
+ * fosa_mutex_destroy()
+ *
+ * Destroy a frsh mutex
+ *
+ * The mutex pointed to by mutex is destroyed
+ *
+ * Returns 0 if successful; otherwise it returns an error code:
+ *    EINVAL: the value of mutex is invalid
+ *    EBUSY:  The mutex is in use (is locked)
+ **/
 int fosa_mutex_destroy(fosa_mutex_t *mutex)
 {
        return pthread_mutex_destroy(mutex);
 }
 
+/**
+ * fosa_mutex_set_prioceiling()
+ *
+ * Dynamically set the priority ceiling of a mutex
+ *
+ * Since in this implementation we use BandWidth Inheritance defining the
+ * ceiling of a mutex is meaningless, and so the function always returns
+ * EINVAL
+ **/
 int fosa_mutex_set_prioceiling(fosa_mutex_t *mutex,
-       int new_ceiling,
-       int *old_ceiling)
+                              int new_ceiling,
+                              int *old_ceiling)
 {
-       return -1;
+       return -EINVAL;
 }
 
+/**
+ * fosa_mutex_get_prioceiling()
+ *
+ * Dynamically get the priority ceiling of a mutex
+ *
+ * Since in this implementation we use BandWidth Inheritance defining the
+ * ceiling of a mutex is meaningless, and so the function always returns
+ * EINVAL
+ **/
 int fosa_mutex_get_prioceiling(const fosa_mutex_t *mutex, int *ceiling)
 {
-       return -1;
+       return -EINVAL;
 }
 
+/**
+ * fosa_mutex_lock()
+ *
+ * Lock a mutex
+ *
+ * This function locks the mutex specified by mutex. If it is already
+ * locked, the calling thread blocks until the mutex becomes
+ * available. The operation returns with the mutex in the locked
+ * state, with the calling thread as its owner.
+ *
+ * Returns 0 if successful; otherwise it returns an error code:
+ *    EINVAL: the value of mutex is invalid, or the priority of the
+ *            calling thread is higher than the priority ceiling of the mutex
+ *    EDEADLK: the current thread already owns this mutex
+ **/
 int fosa_mutex_lock(fosa_mutex_t *mutex)
 {
        return pthread_mutex_lock(mutex);
 }
 
+/**
+ * fosa_mutex_trylock()
+ *
+ * Try locking a mutex
+ *
+ * This function is identical to fosa_mutex_lock() except that if the
+ * mutex is already locked the call returns immediately with an error
+ * indication.
+ *
+ * Returns 0 if successful; otherwise it returns an error code:
+ *    EINVAL: the value of mutex is invalid, or the priority of the
+ *            calling thread is higher than the priority ceiling of the mutex
+ *    EBUSY: the mutex was already locked
+ **/
 int fosa_mutex_trylock(fosa_mutex_t *mutex)
 {
        return pthread_mutex_trylock(mutex);
 }
 
+/**
+ * fosa_mutex_unlock()
+ *
+ * Unlock a mutex
+ *
+ * This function must be called by the owner of the mutex referenced
+ * by mutex, to unlock it. If there are threads blocked on the mutex
+ * the mutex becomes available and the highest priority thread is
+ * awakened to acquire the mutex.
+ *
+ * Returns 0 if successful; otherwise it returns an error code:
+ *     EINVAL: the value of mutex is invalid
+ *     EPERM: the calling thread is not the owner of the mutex
+ **/
 int fosa_mutex_unlock(fosa_mutex_t *mutex)
 {
        return pthread_mutex_unlock(mutex);
@@ -116,35 +201,116 @@ int fosa_mutex_unlock(fosa_mutex_t *mutex)
  * Condition variables
  *********************/
 
+/**
+ * fosa_cond_init()
+ *
+ * Initiatize a condition variable
+ *
+ * The condition variable referenced by cond is initialized with
+ * the attributes required by the FOSA implementation.
+ *
+ *  Returns 0 if successful; otherwise it returns an error code:
+ *     EAGAIN: the system lacked the necessary resources to create the
+ *             condition variable
+ *     ENOMEM: Insufficient memory exists to initialize the condition variable
+ *     EBUSY:  The system has detected an attempt to reinitialize the
+ *             condition variable
+ **/
 int fosa_cond_init(fosa_cond_t *cond)
 {
        return pthread_cond_init(cond, NULL);
 }
 
+/**
+ * fosa_cond_destroy()
+ *
+ * Destroy a condition variable
+ *
+ * The condition variable pointed to by cond is destroyed
+ *
+ * Returns 0 if successful; otherwise it returns an error code:
+ *     EINVAL: the value of cond is invalid
+ *     EBUSY:  The condition variable is in use (a thread is waiting on it)
+ **/
 int fosa_cond_destroy(fosa_cond_t *cond)
 {
        return pthread_cond_destroy(cond);
 }
 
+/**
+ * fosa_cond_signal()
+ *
+ * Signal a condition variable
+ *
+ * This call unblocks at least one of the threads that are waiting on
+ * the condition variable referenced by cond. If there are no threads
+ * waiting, the function has no effect
+ *
+ * Returns 0 if successful; otherwise it returns an error code:
+ *     EINVAL: the value of cond is invalid
+ **/
 int fosa_cond_signal(fosa_cond_t *cond)
 {
        return pthread_cond_signal(cond);
 }
 
+/**
+ * fosa_cond_broadcast()
+ *
+ * Broadcast a condition variable
+ *
+ * This call unblocks all of the threads that are waiting on the
+ * condition variable referenced by cond. If there are no threads
+ * waiting, the function has no effect.
+ *
+ * Returns 0 if successful; otherwise it returns an error code:
+ *     EINVAL: the value of cond is invalid
+ **/
 int fosa_cond_broadcast(fosa_cond_t *cond)
 {
        return pthread_cond_broadcast(cond);
 }
 
+/**
+ * fosa_cond_wait()
+ *
+ * Wait at a condition variable
+ *
+ * This call is used to block on the condition variable referenced by
+ * cond. It shall be called with the mutex referenced by mutex
+ * locked. The function releases the mutex and blocks the calling
+ * thread until the condition is signalled by some other thread and
+ * the calling thread is awakened. Then it locks the mutex and
+ * returns with the mutex locked by the calling thread.
+ *
+ * Returns 0 if successful; otherwise it returns an error code:
+ *    EINVAL: the value of cond or mutex is invalid, or different
+ *            mutexes were used for concurrent wait operations on cond, or
+ *            the mutex was not owned by the calling thread
+ **/
 int fosa_cond_wait(fosa_cond_t *cond, fosa_mutex_t *mutex)
 {
        return pthread_cond_wait(cond, mutex);
 }
 
+/**
+ * fosa_cond_timedwait()
+ *
+ * Wait at a condition variable, with a timeout
+ *
+ * This function is equal to fosa_cond_wait(), except that the maximum
+ * wait time is limited to the absolute time referenced by abstime, as
+ * measured by the FOSA_CLOCK_ABSOLUTE clock.
+ *
+ * Returns 0 if successful; otherwise it returns an error code:
+ *     EINVAL: the value of cond or mutex or abstime is invalid, or different
+ *             mutexes were used for concurrent wait operations on cond, or
+ *             the mutex was not owned by the calling thread
+ *     ETIMEDOUT: the timeout expired
+ **/
 int fosa_cond_timedwait(fosa_cond_t *cond,
        fosa_mutex_t *mutex,
        const struct timespec *abstime)
 {
        return pthread_cond_timedwait(cond, mutex, abstime);
 }
-
index d83b7a21e58e2fcd8d3413a9b86140468403181d..895a567f20e4390ac59c28ea7ec9de26d1676231 100644 (file)
 // FOSA(Frescor Operating System Adaptation layer)
 //================================================
 
-#include <linux/unistd.h>
-#include <unistd.h>
-#include <fosa.h>
+#include "fosa_threads_and_signals.h"
+#include "fosa_configuration_parameters.h"
+
+/*************************
+ * Storage of thread-specific keys
+ *************************/
+
+static pthread_key_t key_list[FOSA_MAX_KEYS];
+static bool key_in_use[FOSA_MAX_KEYS];
+static pthread_mutex_t key_lock;
+
+
+/* Initialize the keys data structure */
+int init_keys()
+{
+       int i, error;
+       pthread_mutexattr_t attr;
+
+       for(i = 0; i < FOSA_MAX_KEYS; i++)
+               key_in_use[i] = false;
+
+       if ((error = pthread_mutexattr_init(&attr)) != 0)
+               return error;
+
+       if ((error = pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_INHERIT)) != 0)
+               return error;
+
+       if ((error = pthread_mutex_init(&key_lock,&attr)) != 0)
+               return error;
+
+       //if ((error = pthread_mutexattr_destroy(&attr)) != 0)
+       //      return error;
+
+       return 0;
+}
 
 /*************************
  * Thread identification
  *************************/ 
 
+/**
+ * fosa_thread_equal()
+ *
+ * Compare two thread identifiers to determine if they refer to the 
+ * same thread
+ **/
 bool fosa_thread_equal(fosa_thread_id_t t1, fosa_thread_id_t t2)
 {
-       if ( pthread_equal(t1.pthread_id, t2.pthread_id &&
-                       t1.linux_pid == t2.linux_pid    &&
-                       t1.linux_tid == t2.linux_tid) )
-               return true;
-
-       return false;
+       return t1.linux_pid == t2.linux_pid &&
+              t1.linux_tid == t2.linux_tid &&
+              pthread_equal(t1.pthread_id, t2.pthread_id);
 }
 
+/**
+ * fosa_thread_self()
+ *
+ * Return the thread id of the calling thread
+ **/
 fosa_thread_id_t fosa_thread_self()
 {
        fosa_thread_id_t thread_self;
-       /* 
-        * Fill the user pointer with appropriate data for the calling thread
+       /** 
         * NB. Remember:
         *  fosa_thread_id_t => struct {
         *                       pthread_t pthread_id;
         *                       pid_t linux_pid;
         *                       tid_t linux_tid;
         * };
-        */
-       thread_self.pthread_id = pthread_self();        /* only valid for threads! */
+        **/
+       thread_self.pthread_id = pthread_self();
        thread_self.linux_pid = getpid();
-       thread_self.linux_tid = syscall(__NR_gettid);   /* equal to gettid() */
+       thread_self.linux_tid = syscall(__NR_gettid);   /* gettid() */
 
        return thread_self;
 }
 
+/*************************
+ * Thread attributes
+ *************************/
+
+/**
+ * fosa_thread_attr_init()
+ *
+ * Initialize a thread attributes object
+ *
+ * This function initializes the object pointed to by attr to all 
+ * the default values defined by FRSH
+ *
+ * return 0 if successful; otherwise it returns
+ *   FOSA_ENOMEM: insufficient memory exists to initialize the thread 
+ *           attributes object
+ **/
+int fosa_thread_attr_init(fosa_thread_attr_t *attr)
+{
+       fosa_thread_id_t self;
+
+       /* only POSIX threads have attributes */
+       self = fosa_thread_self();
+       if (self.linux_pid == self.linux_tid)
+               return EINVAL;
+
+       return pthread_attr_init(attr);
+}
+
+/**
+ * fosa_thread_attr_destroy()
+ *
+ * Destroy a thread attributes object
+ *
+ * This function is used to destroy the thread attributes object,
+ * pointed to by attr, and deallocate any system resources allocated for it
+ * 
+ * Returns 0
+ */
+int fosa_thread_attr_destroy(fosa_thread_attr_t *attr)
+{
+       fosa_thread_id_t self;
+
+       /* only POSIX threads can have attributes */
+       self = fosa_thread_self();
+       if (self.linux_pid == self.linux_tid)
+               return EINVAL;
+
+       return pthread_attr_destroy(attr);
+}
+
+/**
+ * fosa_thread_attr_set_stacksize()
+ *
+ * Set the thread minimum stack size in a thread attributes object
+ *
+ * This function sets the minimum stack size of the thread attributes
+ * object attr to the value given by stacksize, in bytes. This
+ * function has no runtime effect on the stack size, except when the
+ * attributes object is used to create a thread, when it will be
+ * created with the specified minimum stack size
+ * 
+ * return 0 if successful, or the following error code:
+ *    FOSA_EINVAL: the specified stacksize  value is not supported in
+ *            this implementation
+ */
+int fosa_thread_attr_set_stacksize(fosa_thread_attr_t *attr,
+                                  size_t stacksize)
+{
+       fosa_thread_id_t self;
+
+       /* only POSIX threads can set the size of the stack */
+       self = fosa_thread_self();
+       if (self.linux_pid == self.linux_tid)
+               return EINVAL;
+
+       return pthread_attr_setstacksize(attr, stacksize);
+}
+
+/**
+ * fosa_thread_attr_get_stacksize()
+ *
+ * Get the thread minimum stack size from a thread attributes object
+ *
+ * This function sets the variable pointed to by stacksize to the
+ * minimum stack size stored in the thread attributes object attr.
+ * 
+ * return 0
+ */
+int fosa_thread_attr_get_stacksize(const fosa_thread_attr_t *attr,
+                                  size_t *stacksize)
+{
+       fosa_thread_id_t self;
+
+       /* only POSIX threads can set the size of the stack */
+       self = fosa_thread_self();
+       if (self.linux_pid == self.linux_tid)
+               return EINVAL;
+
+       return pthread_attr_getstacksize(attr, stacksize);
+}
+
 /*************************
  * Thread creation and termination
- *************************/ 
+ *************************/
 
+/**
+ * fosa_thread_create()
+ *
+ * This function creates a new thread using the attributes specified
+ * in attr. If attr is NULL, default attributes are used. The new
+ * thread starts running immediately, executing the function specified
+ * by code, with an argument equal to arg. Upon successful return, the
+ * variable pointed to by tid will contain the identifier of the newly
+ * created thread. The set of signals that may be synchronously
+ * accepted is inherited from the parent thread.
+ *
+ * Returns 0 if successful; otherwise it returs a code error:
+ *
+ *     EAGAIN: the system lacks the necessary resources to create a
+ *             new thread or the maximum number of threads has been
+ *             reached
+ *
+ *     EINVAL: the value specified by attr is invalid (for instance,
+ *              it has not been correctly initialized)
+ *
+ *     EREJECT: the cretion of the thread was rejected by the frsh scheduler
+ *               possibly because of incorrect attributes, or because the 
+ *               requested minimum capacity cannot be guaranteed
+ **/
 int fosa_thread_create(fosa_thread_id_t *tid,
-       const fosa_thread_attr_t *attr,
-       fosa_thread_code_t code,
-       void *arg)
+                      const fosa_thread_attr_t *attr,
+                      fosa_thread_code_t code,
+                      void *arg)
 {
-       pthread_t tmp_tid;
-
-       /* 'tid' can't be used, act other ways
-        * to get the thread id of the new thread */
-       return pthread_create(&tmp_tid,attr,code, arg);
+       return pthread_create(&tid->pthread_id, attr, code, arg);
 }
 
+/**
+ * Note: no thread termination primitive is provided. The termination
+ * of a thread will be notified by the system to the FRSH scheduler
+ * through the scheduler API
+ **/
+
 /**************************************************
  * Thread-specific data
  *  (extended with access from a different thread)
@@ -120,34 +286,140 @@ int fosa_thread_create(fosa_thread_id_t *tid,
  * deallocating the memory area pointed to by the pointer
  **************************************************/ 
 
-int fosa_thread_set_specific_data(int key,
-       fosa_thread_id_t tid,
-       const void *value)
+/**
+ * fosa_key_create()
+ *
+ * Create a new key for thread specific data.
+ *
+ * Prior to setting data in a key, we need ask the system to create
+ * one for us.
+ *
+ * return 0 if successful \n
+ *   FOSA_EINVAL If we already have reached the FOSA_MAX_KEYS limit.
+ *   FOSA_ENOMEM If there are no enough memory resources to 
+ *               create the key.
+ **/
+int fosa_key_create(int *key)
+{
+       int i, error = 0;
+       bool found = false;
+       fosa_thread_id_t self;
+
+       /* only POSIX threads can have specific data */
+       self = fosa_thread_self();
+       if (self.linux_pid == self.linux_tid)
+               return EINVAL;
+
+       if ((error = pthread_mutex_lock(&key_lock)) != 0)
+               return error;
+
+       /* find an unused key */
+       for (i = 0; i < FOSA_MAX_KEYS; i++) {
+               if (!key_in_use[i]) {
+                       *key = i;
+                       key_in_use[i] = true;
+                       error = pthread_key_create(&(key_list[i]), NULL);
+                       found = true;
+                       break;
+               }
+       }
+
+       if ((error = pthread_mutex_unlock(&key_lock))!= 0)
+               return error;
+
+       return (!found ? FOSA_EINVAL : error);
+}
+
+/**
+ * fosa_key_destroy()
+ *
+ * Destroy a key
+ *
+ * This destroys the key and isables its use in the system
+ *
+ * return 0 if successful
+ *   FOSA_EINVAL The key is not initialised or is not in FOSA key range.
+ **/
+int fosa_key_destroy(int key)
+{
+       int error;
+       fosa_thread_id_t self;
+
+       /* only POSIX threads can have specific data */
+       self = fosa_thread_self();
+       if (self.linux_pid == self.linux_tid)
+               return EINVAL;
+
+       if ((error = pthread_mutex_lock(&key_lock)) != 0)
+               return error;
+
+       if ((error = pthread_key_delete(key_list[key])) != 0)
+               key_in_use[key]=false;
+
+       if ((error = pthread_mutex_unlock(&key_lock)) != 0)
+               return error;
+
+       return 0;
+}
+
+
+/**
+ * fosa_thread_set_specific_data()
+ *
+ * Set thread-specific data
+ *
+ * For the thread identified by tid, the thread-specifid data field
+ * identified by key will be set to the value specified by value
+ * 
+ * In this implementation, according to POSIX, the accessed data field
+ * is the one of the calling thread, not the one specified via tid.
+ *
+ * Returns 0 if successful; otherwise, an error code is returned
+ *     EINVAL: the value of key is not between 0 and FOSA_MAX_KEYS-1
+ **/
+ int fosa_thread_set_specific_data(int key,
+                                  fosa_thread_id_t tid,
+                                  const void * value)
 {
-       //if ((key > 0) && (key < (FOSA_MAX_KEYS-1))) {
-       //      tid.pthread_id->tsd[key] = (void *) value;
-       //
-       //      return 0;
-       //}
-
-       errno = EINVAL;
-       return -1;
+       fosa_thread_id_t self;
+
+       /* only POSIX threads can have specific data */
+       self = fosa_thread_self();
+       if (self.linux_pid == self.linux_tid)
+               return EINVAL;
+
+       return pthread_setspecific(key_list[key], value);
 }
 
+/**
+ * fosa_thread_get_specific_data()
+ *
+ * Get thread-specific data
+ *
+ * For the thread identified by tid, the thread-specifid data field
+ * identified by key will be copied to the variable pointed to by value
+ * 
+ * In this implementation, according to POSIX, the accessed data field
+ * is the one of the calling thread, not the one specified via tid.
+ *
+ * Returns 0 if successful; otherwise, an error code is returned
+ *     EINVAL: the value of key is not between 0 and FOSA_MAX_KEYS-1
+ **/
 int fosa_thread_get_specific_data(int key,
-       fosa_thread_id_t tid,
-       void **value)
+                                 fosa_thread_id_t tid,
+                                 void ** value)
 {
-       //if ((key > 0) && (key < (FOSA_MAX_KEYS-1))) {
-       //      *value=pthread_remote_getspecific(key,tid);
-       //      *value=tid.pthread_id->tsd[key];
-       //
-       //      return 0;
-       //}
+       fosa_thread_id_t self;
 
-       errno = EINVAL;
-       return -1;
+       /* only POSIX threads can have specific data */
+       self = fosa_thread_self();
+       if (self.linux_pid == self.linux_tid)
+               return EINVAL;
 
+       if ((value = pthread_getspecific(key_list[key])) != NULL)
+               return EINVAL;
+       else
+               return 0;
 }
 
 /******************************************************************
@@ -161,53 +433,140 @@ int fosa_thread_get_specific_data(int key,
  * mapping is automatically provided by the OS adaptation layer.
  *******************************************************************/
 
-int fosa_get_priority_max() {
-       return sched_get_priority_max(0);
+/**
+ * fosa_get_priority_max()
+ *
+ * Return the maximum priority value used in this implementation
+ **/
+int fosa_get_priority_max()
+{
+       return sched_get_priority_max(SCHED_FIFO);
 }
 
-int fosa_get_priority_min() {
-       return sched_get_priority_min(0);
+/**
+ * fosa_get_priority_min()
+ *
+ * Return the minimum priority value used in this implementation
+ **/
+int fosa_get_priority_min()
+{
+       return sched_get_priority_min(SCHED_FIFO);
 }
 
+/**
+ * fosa_thread_attr_set_prio()
+ *
+ * Change the priority of a thread attributes object
+ *
+ * The priority of the thread attriutes object specified by attr is
+ * set to the value specified by prio. This function has no runtime
+ * effect on the priority, except when the attributes object is used
+ * to create a thread, when it will be created with the specified
+ * priority
+ * 
+ * Returns 0 if successful, or the following error code:
+ *    EINVAL: the specified priority value is not between the 
+ *            minimum and the maximum priorities defined in this
+ *            FRSH implementation
+ **/
 int fosa_thread_attr_set_prio(fosa_thread_attr_t *attr, int prio)
 {
-       //if ((sched_get_priority_min(0)<=prio) || (prio<=sched_get_priority_min(0))) {
-       //      attr->sched_param.sched_priority = prio;
-       //
-       //      return 0;
-       //}
-
-       errno = EINVAL;
-       return -1;
+       fosa_thread_id_t self;
+       struct sched_param param;
+
+       /* normal UNIX processes have no attributes */
+       self = fosa_thread_self();
+       if (self.linux_pid == self.linux_tid)
+               return EINVAL;
+       
+       param.sched_priority = prio;
+
+       return pthread_attr_setschedparam(attr, &param);
 }
 
-int fosa_thread_attr_get_prio (const fosa_thread_attr_t *attr, int *prio)
+/**
+ * fosa_thread_attr_get_prio()
+ *
+ * Get the priority from a thread attributes object
+ *
+ * This function sets the variable pointed to by prio to the
+ * priority stored in the thread attributes object attr.
+ * 
+ * Returns 0
+ **/
+int fosa_thread_attr_get_prio(const fosa_thread_attr_t *attr, int *prio)
 {
-       //*prio = attr->sched_param.sched_priority;
-       //return 0;
+       int error;
+       fosa_thread_id_t self;
+       struct sched_param param;
+
+       /* normal UNIX processes have no attributes */
+       self = fosa_thread_self();
+       if (self.linux_pid == self.linux_tid)
+               return EINVAL;
 
-       errno = EINVAL;
-       return -1;
+       if ((error = pthread_attr_getschedparam(attr, &param)) == 0)
+               *prio = param.sched_priority;
+
+       return error;
 }
 
+/**
+ * fosa_thread_set_prio()
+ *
+ * Dynamically change the priority of a thread
+ *
+ * The priority of the thread identified by tid is
+ * set to the value specified by prio. 
+ * 
+ * Returns 0 if successful, or the following error code:
+ *    EINVAL: the specified priority value is not between the 
+ *            minimum and the maximum priorities defined in this
+ *            FRSH implementation
+ **/
 int fosa_thread_set_prio(fosa_thread_id_t tid, int prio)
 {
-       //if ((sched_get_priority_min(0)<=prio) || (prio<=sched_get_priority_min(0))) {
-       //      pthread_setschedprio(tid.pthread_id,prio);
-       //      return 0;
-       //}
-
-       errno = EINVAL;
-       return -1;
+       struct sched_param param;
+       int error;
+
+       param.sched_priority=prio;
+       if (tid.linux_pid == tid.linux_tid)
+               error = sched_setscheduler(tid.linux_pid,
+                                          SCHED_RR,
+                                          &param);
+       else
+               error = pthread_setschedparam(tid.pthread_id,
+                                              SCHED_RR,
+                                              &param);
+
+       return error;
 }
 
+/**
+ * fosa_thread_get_prio()
+ *
+ * Dynamically get the priority of a thread
+ *
+ * This function sets the variable pointed to by prio to the
+ * priority of the thread identified by tid
+ * 
+ * Returns 0
+ **/
 int fosa_thread_get_prio (fosa_thread_id_t tid, int *prio)
 {
-       //*prio = tid.pthread_id->sched_param.sched_priority;
-       //return 0;
+       struct sched_param param;
+       int policy, error;
+
+       if (tid.linux_pid == tid.linux_tid)
+               error = sched_getparam(tid.linux_pid, &param);
+       else
+               error = pthread_getschedparam(tid.pthread_id,
+                                             &policy,
+                                             &param);
 
-       errno = EINVAL;
-       return -1;
+       *prio = param.sched_priority;
+
+       return error;
 }
 
 /*******************************************************************
@@ -223,86 +582,167 @@ int fosa_thread_get_prio (fosa_thread_id_t tid, int *prio)
  * values.
  *******************************************************************/
 
-/* it's an hack and it does not work!
- * We need to change the API if we want such a feature!!*/
-sigset_t original_mask;
-
+/**
+ * fosa_set_accepted_signals()
+ *
+ * Establish the set of signals that may be synchronously accepted 
+ * by the calling thread
+ *
+ * The function uses the array of signal numbers specified by set,
+ * which must be of size equal to size
+ *
+ * Returns 0 if successful; otherwise it returns an error code:
+ *     EINVAL: the array contains one or more values which are not
+ *             between FOSA_SIGNAL_MIN and FOSA_SIGNAL_MAX, or size
+ *             is less than 0
+ **/
 int fosa_set_accepted_signals(fosa_signal_t set[], int size)
 {
-       int x;
-       sigset_t new_mask;
-
-       /* all signal blocked by default */
-       sigfillset(&new_mask);
-       for (x = 0; x < size; x++)
-               /* unblock only the signals in 'set' */
-               sigdelset(&new_mask, set[x]);
-
-       /* NB. save the original mask in the
-        * default variable... Orrible hack!! :-( */
-       return pthread_sigmask(SIG_SETMASK, &new_mask, &original_mask);
+       int i, error;
+       fosa_thread_id_t self;
+       sigset_t sigset;
+       struct sigaction action;
+
+       if ((error = sigemptyset(&sigset)) != 0)
+               return error;
+
+       /* real-time signal (can be queued) */
+       action.sa_handler = SIG_DFL;
+       action.sa_mask = sigset;
+       action.sa_flags = SA_SIGINFO;
+       action.sa_sigaction = NULL;
+
+       for (i = 0; i < size; i++) {
+               if ((error = sigaddset(&sigset, set[i])) != 0)
+                       return error;
+               if ((error = sigaction(set[i], &action, NULL)) != 0)
+                       return error;
+       }
+
+       self = fosa_thread_self();
+       if (self.linux_pid == self.linux_tid)
+               return pthread_sigmask(SIG_BLOCK, &sigset, NULL);
+       else
+               return sigprocmask(SIG_BLOCK, &sigset, NULL);
 }
 
+/**
+ * fosa_signal_queue()
+ *
+ * Queue a signal
+ *
+ * This function is used to explicitly send a signal with a specified
+ * value
+ * 
+ * The signal number specified by signal is sent together with the
+ * information specified by info, to the thread identified by
+ * receiver.
+ * 
+ * Note that, in this implementation, the signal is sent to any thread
+ * waiting for it (maybe via fosa_signal_wait()).
+ * If needed ensure the receiver is the only one who is waiting for the
+ * signal (e.g., by using different signal numbers for each thread). 
+ *
+ * Returns 0 if successful; otherwise it returns an error code:
+ *     EINVAL: the signal specified by signal is not
+ *              between FOSA_SIGNAL_MIN and FOSA_SIGNAL_MAX
+ *
+ *     EAGAIN: no resources are available to queue the signal; the
+ *             maximum number of queued signals has been reached, or a
+ *             systemwide resource limit has been exceeded
+ **/
 int fosa_signal_queue(fosa_signal_t signal,
-       fosa_signal_info_t info,
-       fosa_thread_id_t receiver)
+                     fosa_signal_info_t info,
+                     fosa_thread_id_t receiver)
 {
-       union sigval siginfo;
-
-       siginfo.sival_int = info.sival_int;
-       return sigqueue(receiver.linux_pid, signal, siginfo);
+       /* Note: signal sent to a "whole" process */
+       return sigqueue(receiver.linux_pid, signal, *((union sigval*) &info));
 }
 
-int fosa_signal_wait (fosa_signal_t set[],
-       int size,
-       fosa_signal_t *signal_received,
-       fosa_signal_info_t *info)
+/**
+ * fosa_signal_wait()
+ *
+ * Wait for a signal
+ * 
+ * The function waits for the arrival of one of the signals in the
+ * array of signal numbers specified by set, which must be of size
+ * equal to size. If there is a signal already queued, the function
+ * returns immediately. If there is no signal of the specified set
+ * queued, the calling thread is suspended until a signal from that
+ * set arrives. Upon return, if signal_received is not NULL the number
+ * of the signal received is stored in the variable pointed to by
+ * signal_received; and if info is not NULL the associated information
+ * is stored in the variable pointed to by info.
+ *
+ * Returns 0 if successful; otherwise it returns an error code:
+ *     EINVAL: the array contains one or more values which are not
+ *             between FOSA_SIGNAL_MIN and FOSA_SIGNAL_MAX, or size
+ *             is less than 0
+ **/
+int fosa_signal_wait(fosa_signal_t set[], int size,
+                    fosa_signal_t *signal_received,
+                    fosa_signal_info_t *info)
 {
-       int x;
-       sigset_t wait_mask;
-       siginfo_t recv_signal_info;
-
-       /* only wait for the signals in 'set' */
-       sigemptyset(&wait_mask);
-       for (x = 0; x < size; x++)
-               sigaddset(&wait_mask, set[x]);
-       /* go to sleep and let's hope someone wake up us !! */
-       if (sigwaitinfo(&wait_mask, &recv_signal_info) < 0)
-               return -1;
-       /* return back informations for the caller */
-       *signal_received = recv_signal_info.si_signo;
-       info->sival_int = recv_signal_info.si_value.sival_int;
-       /* reset the signal mask to original one (orrible hack!!) */
-       pthread_sigmask(SIG_SETMASK, &original_mask, NULL);
+       int i, error;
+       sigset_t sigset;
+       siginfo_t siginfo;
+
+       if ((error = sigemptyset(&sigset)) != 0)
+               return error;
+
+       for (i = 0; i < size; i++)
+               if ((error = sigaddset(&sigset,set[i])) != 0)
+                       return error;
+
+       if ((error = sigwaitinfo(&sigset, &siginfo)) != 0)
+               return error;
+
+       if (signal_received != NULL)
+               *signal_received = siginfo.si_signo;
+       if (info != NULL)
+               *info = (fosa_signal_info_t) siginfo.si_value.sival_int;
 
        return 0;
 }
 
-int fosa_signal_timedwait(fosa_signal_t set[],
-       int size,
-       fosa_signal_t *signal_received,
-       fosa_signal_info_t *info,
-       const struct timespec *timeout)
+/**
+ * fosa_signal_timedwait()
+ *
+ * Timed wait for a signal
+ * 
+ * This function behaves the same as fosa_signal_wait(), except that
+ * the suspension time is limited to the time interval specified in
+ * the timespec structure referenced by timeout.
+ * 
+ * Returns 0 if successful; otherwise it returns an error code:
+ *     EINVAL: the array contains one or more values which are not
+ *             between FOSA_SIGNAL_MIN and FOSA_SIGNAL_MAX, or size
+ *             is less than 0, or timeout is invalid
+ *     EAGAIN: The timeout expired
+ **/
+int fosa_signal_timedwait(fosa_signal_t set[], int size,
+                         fosa_signal_t *signal_received,
+                         fosa_signal_info_t *info,
+                         const struct timespec *timeout)
 {
-       int x;
-       sigset_t wait_mask;
-       siginfo_t recv_signal_info;
-
-       /* only wait for the signals in 'set' */
-       sigemptyset(&wait_mask);
-       for (x = 0; x < size; x++)
-               sigaddset(&wait_mask, set[x]);
-       /* go to sleep and let's hope someone wake up us !! */
-       if (sigtimedwait(&wait_mask, &recv_signal_info, timeout) < 0)
-               return -1;
-       /* return back informations for the caller */
+       int i, error;
+       sigset_t signalset;
+       siginfo_t siginfo;
+
+       if ((error = sigemptyset(&signalset)) != 0)
+               return error;
+
+       for (i = 0; i < size; i++)
+               if ((error = sigaddset(&signalset,set[i])) != 0)
+                       return error;
+
+       if ((error = sigtimedwait(&signalset,&siginfo,timeout)) != 0)
+               return error;
+
        if (signal_received != NULL)
-               *signal_received = recv_signal_info.si_signo;
+               *signal_received = siginfo.si_signo;
        if (info != NULL)
-               info->sival_int = recv_signal_info.si_value.sival_int;
-       /* reset the signal mask to original one (orrible hack!!) */
-       pthread_sigmask(SIG_SETMASK, &original_mask, NULL);
+               *info = (fosa_signal_info_t) siginfo.si_value.sival_int;
 
-       return 0; 
+       return 0;
 }
-
diff --git a/src_aquosa/fosa_time.c b/src_aquosa/fosa_time.c
new file mode 100644 (file)
index 0000000..07c312d
--- /dev/null
@@ -0,0 +1,110 @@
+//----------------------------------------------------------------------
+//  Copyright (C) 2006 - 2007 by the FRESCOR consortium:
+//
+//    Universidad de Cantabria,              SPAIN
+//    University of York,                    UK
+//    Scuola Superiore Sant'Anna,            ITALY
+//    Kaiserslautern University,             GERMANY
+//    Univ. Politecnica  Valencia,           SPAIN
+//    Czech Technical University in Prague,  CZECH REPUBLIC
+//    ENEA                                   SWEDEN
+//    Thales Communication S.A.              FRANCE
+//    Visual Tools S.A.                      SPAIN
+//    Rapita Systems Ltd                     UK
+//    Evidence                               ITALY
+//
+//    See http://www.frescor.org
+//
+//        The FRESCOR project (FP6/2005/IST/5-034026) is funded
+//        in part by the European Union Sixth Framework Programme
+//        The European Union is not liable of any use that may be
+//        made of this code.
+//
+//
+//  based on previous work (FSF) done in the FIRST project
+//
+//   Copyright (C) 2005  Mälardalen University, SWEDEN
+//                       Scuola Superiore S.Anna, ITALY
+//                       Universidad de Cantabria, SPAIN
+//                       University of York, UK
+//
+// This file is part of FOSA (Frsh Operating System Abstraction)
+//
+// FOSA is free software; you can redistribute it and/or modify it
+// under terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option) any
+// later version.  FOSA is distributed in the hope that it will be
+// useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details. You should have received a
+// copy of the GNU General Public License along with FOSA; see file
+// COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,
+// Cambridge, MA 02139, USA.
+//
+// As a special exception, including FOSA header files in a file,
+// instantiating FOSA generics or templates, or linking other files
+// with FOSA objects to produce an executable application, does not
+// by itself cause the resulting executable application to be covered
+// by the GNU General Public License. This exception does not
+// however invalidate any other reasons why the executable file might be
+// covered by the GNU Public License.
+// -----------------------------------------------------------------------
+// fosa_time.c
+//==============================================
+//  ********  ******    ********  **********
+//  **///// /**    **  **//////  /**     /**
+//  **      /**    ** /**        /**     /**
+//  ******* /**    ** /********* /**********
+//  **////  /**    ** ////////** /**//////**
+//  **      /**    **        /** /**     /**
+//  **      /**    **  ********  /**     /**
+//  //       /******/  ////////   //      // 
+//
+// FOSA(Frescor Operating System Adaptation layer)
+//================================================
+
+#include "fosa_time.h"
+#include "fosa_threads_and_signals.h"
+
+#define timespec_add(t1, t2, sum)                      \
+ do {                                                  \
+   (sum)->tv_sec = (t1).tv_sec + (t2).tv_sec;          \
+   (sum)->tv_nsec = (t1).tv_nsec + (t2).tv_nsec;       \
+   if ((sum)->tv_nsec >= 1000000000) {                 \
+     (sum)->tv_sec++;                                  \
+     (sum)->tv_nsec -= 1000000000;                     \
+   }                                                   \
+ } while (0)
+
+#define timespec_smaller(t1, t2)                               \
+ ( (t1).tv_sec < (t2).tv_sec || ((t1).tv_sec == (t2).tv_sec && \
+   (t1).tv_nsec < (t2).tv_nsec) )
+
+/**
+ * fosa_eat()
+ *
+ * Eat some time using system clock facilities
+ **/
+void inline fosa_eat(const struct timespec *cpu_time)
+{
+       int error;
+       fosa_thread_id_t self;
+       clockid_t clock_id;
+       struct timespec current_time, time_to_go;
+
+       self = fosa_thread_self();
+       if (self.linux_pid == self.linux_tid)
+               error = clock_getcpuclockid(self.linux_pid, &clock_id);
+       else
+               error = pthread_getcpuclockid(self.pthread_id, &clock_id);
+       if (error != 0)
+               return;
+
+       if (clock_gettime(clock_id, &current_time) != 0)
+                       return;
+
+       timespec_add(current_time, *cpu_time, &time_to_go);
+       while (timespec_smaller(current_time, time_to_go))
+               if (clock_gettime(clock_id, &current_time) != 0)
+                       return;
+}
diff --git a/src_aquosa/frsh_fosa.c b/src_aquosa/frsh_fosa.c
deleted file mode 100644 (file)
index f2a2d57..0000000
+++ /dev/null
@@ -1,144 +0,0 @@
-// -----------------------------------------------------------------------
-//  Copyright (C) 2006 - 2007 FRESCOR consortium partners:
-//
-//    Universidad de Cantabria,              SPAIN
-//    University of York,                    UK
-//    Scuola Superiore Sant'Anna,            ITALY
-//    Kaiserslautern University,             GERMANY
-//    Univ. Politecnica  Valencia,           SPAIN
-//    Czech Technical University in Prague,  CZECH REPUBLIC
-//    ENEA                                   SWEDEN
-//    Thales Communication S.A.              FRANCE
-//    Visual Tools S.A.                      SPAIN
-//    Rapita Systems Ltd                     UK
-//    Evidence                               ITALY
-//    
-//    See http://www.frescor.org for a link to partners' websites
-//
-//           FRESCOR project (FP6/2005/IST/5-034026) is funded
-//        in part by the European Union Sixth Framework Programme
-//        The European Union is not liable of any use that may be
-//        made of this code.
-//
-//  This file is part of the FRSH implementation
-//
-//  FRSH is free software; you can  redistribute it and/or  modify
-//  it under the terms of  the GNU General Public License as published by
-//  the Free Software Foundation;  either  version 2, or (at  your option)
-//  any later version.
-//
-//  FRSH  is distributed  in  the hope  that  it  will  be useful,  but
-//  WITHOUT  ANY  WARRANTY;     without  even the   implied   warranty  of
-//  MERCHANTABILITY  or  FITNESS FOR  A  PARTICULAR PURPOSE. See  the  GNU
-//  General Public License for more details.
-//
-//  You should have  received a  copy of  the  GNU  General Public License
-//  distributed  with  FRSH;  see file COPYING.   If not,  write to the
-//  Free Software  Foundation,  59 Temple Place  -  Suite 330,  Boston, MA
-//  02111-1307, USA.
-//
-// -----------------------------------------------------------------------
-//frsh_fosa.c
-//==============================================
-//  ********  ******    ********  **********
-//  **///// /**    **  **//////  /**     /**
-//  **      /**    ** /**        /**     /**
-//  ******* /**    ** /********* /**********
-//  **////  /**    ** ////////** /**//////**
-//  **      /**    **        /** /**     /**
-//  **      /**    **  ********  /**     /**
-//  //       /******/  ////////   //      // 
-//
-// FOSA(Frescor Operating System Adaptation layer)
-//================================================
-
-#include "frsh_fosa.h"
-
-/*************************
- * Thread attributes
- *************************/ 
-
-/**
- * frsh_thread_attr_init()
- *
- * Initialize a thread attributes object
- *
- * This function initializes the object pointed to by attr to all 
- * the default values defined by FRSH
- *
- * @return 0 if successful; otherwise it returns \n
- *   FOSA_ENOMEM: insufficient memory exists to initialize the thread 
- *           attributes object
- **/
-int frsh_thread_attr_init(frsh_thread_attr_t *attr)
-{
-       int ret_value;
-
-       ret_value=pthread_attr_init(attr);
-       /* if (ret_value==0) {
-               // set the default values
-               detachstate = detached thread (no join operation allowed)
-               CHK(pthread_attr_setdetachstate(attr,PTHREAD_CREATE_DETACHED));
-               // inheritsched = explicit, so that we can explicitly set the attributes
-               CHK(pthread_attr_setinheritsched(attr,PTHREAD_EXPLICIT_SCHED));
-               // schedpolicy = fixed priorities
-               CHK(pthread_attr_setschedpolicy(attr,SCHED_FIFO));
-               // detachstate = detached thread (no join operation allowed)
-               CHK(pthread_attr_setdetachstate(attr,PTHREAD_CREATE_DETACHED));
-       } */
-
-       return ret_value;
-}
-
-/**
- * frsh_thread_attr_destroy()
- *
- * Destroy a thread attributes object
- *
- * This function is used to destroy the thread attributes object,
- * pointed to by attr, and deallocate any system resources allocated for it
- * 
- * Returns 0
- */
-int frsh_thread_attr_destroy(frsh_thread_attr_t *attr)
-{
-       return pthread_attr_destroy(attr);
-}
-
-/**
- * frsh_thread_attr_set_stacksize()
- *
- * Set the thread minimum stack size in a thread attributes object
- *
- * This function sets the minimum stack size of the thread attributes
- * object attr to the value given by stacksize, in bytes. This
- * function has no runtime effect on the stack size, except when the
- * attributes object is used to create a thread, when it will be
- * created with the specified minimum stack size
- * 
- * @return 0 if successful, or the following error code:
- *    FOSA_EINVAL: the specified stacksize  value is not supported in
- *            this implementation
- */
-int frsh_thread_attr_set_stacksize(frsh_thread_attr_t *attr,
-       size_t stacksize)
-{
-       return pthread_attr_setstacksize(attr,stacksize);
-}
-
-/**
- * frsh_thread_attr_get_stacksize()
- *
- * Get the thread minimum stack size from a thread attributes object
- *
- * This function sets the variable pointed to by stacksize to the
- * minimum stack size stored in the thread attributes object attr.
- * 
- * @return 0
- */
-int frsh_thread_attr_get_stacksize(const frsh_thread_attr_t *attr,
-       size_t *stacksize)
-{
-       return pthread_attr_getstacksize(attr,stacksize);
-}
-