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 \
../lib/$(SHARED_NAME): $(OBJS)
@exec echo -n "=> Generating libfosa_qres.so: ";
- $(CC) -shared -o $@ $(OBJS)
+ @$(CC) -shared -o $@ $(OBJS)
@exec echo " [OK]"
###############################################################
%.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 #
// 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);
}
* 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);
}
// 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);
* 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);
}
-
// 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)
* 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;
}
/******************************************************************
* 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, ¶m);
}
-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, ¶m)) == 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,
+ ¶m);
+ else
+ error = pthread_setschedparam(tid.pthread_id,
+ SCHED_RR,
+ ¶m);
+
+ 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, ¶m);
+ else
+ error = pthread_getschedparam(tid.pthread_id,
+ &policy,
+ ¶m);
- errno = EINVAL;
- return -1;
+ *prio = param.sched_priority;
+
+ return error;
}
/*******************************************************************
* 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;
}
-
--- /dev/null
+//----------------------------------------------------------------------
+// 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, ¤t_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, ¤t_time) != 0)
+ return;
+}
+++ /dev/null
-// -----------------------------------------------------------------------
-// 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);
-}
-