// FOSA(Frescor Operating System Adaptation layer)
//================================================
-#include <linux/unistd.h>
-#include <unistd.h>
-#include <fosa.h>
+#include "fosa_time.h"
+#include "fosa_configuration_parameters.h"
+#include "fosa_threads_and_signals.h"
+
+#ifdef OMK_FOR_USER /* If compiled by OMK, use the config */
+#include "fosa_config.h"
+#endif
+
+/*************************
+ * 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, ret;
+ pthread_mutexattr_t attr;
+
+ for(i = 0; i < FOSA_MAX_KEYS; i++)
+ key_in_use[i] = false;
+
+ ret = pthread_mutexattr_init(&attr);
+ if (ret) return errno;
+
+#ifndef CONFIG_NO_PRIO_INHERIT /* Not supported on older systems */
+ ret = pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_INHERIT);
+ if (ret) return errno;
+#endif
+
+ ret = pthread_mutex_init(&key_lock,&attr);
+ if (ret) return errno;
+
+ return 0;
+}
/*************************
* Thread identification
*************************/
-bool fosa_thread_equal(frsh_thread_id_t t1, frsh_thread_id_t t2)
+/**
+ * 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);
}
-frsh_thread_id_t fosa_thread_self()
+/**
+ * fosa_thread_self()
+ *
+ * Return the thread id of the calling thread
+ **/
+fosa_thread_id_t fosa_thread_self()
{
- frsh_thread_id_t thread_self;
- /*
- * Fill the user pointer with appropriate data for the calling thread
+ fosa_thread_id_t thread_self;
+ /**
* NB. Remember:
- * frsh_thread_id_t => struct {
+ * 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 creation and termination
- *************************/
+ * Thread attributes
+ *************************/
+
+static inline int __fosa_check_thread(const fosa_thread_id_t *tid)
+{
+ if (tid->linux_pid == tid->linux_tid)
+ return 0;
+
+ return 1;
+}
+
+/**
+ * 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)
+{
+ 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)
+{
+ 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)
+{
+ return pthread_attr_setstacksize(attr, stacksize);
+}
-int fosa_thread_create(frsh_thread_id_t *tid,
- const frsh_thread_attr_t *attr,
- frsh_thread_code_t code,
- void *arg)
+/**
+ * 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)
{
- pthread_t tmp_tid;
+ return pthread_attr_getstacksize(attr, stacksize);
+}
+
+/*************************
+ * Thread creation and termination
+ *************************/
- /* '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);
+/**
+ * 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)
+{
+ 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,
- frsh_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, ret;
+ bool found = false;
+
+ ret = pthread_mutex_lock(&key_lock);
+ if (ret) return ret;
+
+ /* find an unused key */
+ for (i = 0; i < FOSA_MAX_KEYS; i++) {
+ if (!key_in_use[i]) {
+ ret = pthread_key_create(&(key_list[i]), NULL);
+ if (ret) return ret;
+
+ *key = i;
+ key_in_use[i] = true;
+ found = true;
+
+ break;
+ }
+ }
+
+ ret = pthread_mutex_unlock(&key_lock);
+ if (ret) return ret;
+
+ return (!found ? FOSA_EINVAL : ret);
+}
+
+/**
+ * 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 ret;
+
+ ret = pthread_mutex_lock(&key_lock);
+ if (ret) return ret;
+
+ ret = pthread_key_delete(key_list[key]);
+ if (ret) return ret;
+
+ key_in_use[key]=false;
+
+ ret = pthread_mutex_unlock(&key_lock);
+ if (ret) return ret;
+
+ 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;
+ int ret;
+
+ /* only POSIX threads can have specific data */
+ if (!__fosa_check_thread(&tid))
+ return FOSA_EINVAL;
+
+ ret = pthread_setspecific(key_list[key], value);
+
+ return ret ? ret : 0;
}
+/**
+ * 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,
- frsh_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;
- //}
+ /* only POSIX threads can have specific data */
+ if (!__fosa_check_thread(&tid))
+ return EINVAL;
- errno = EINVAL;
- return -1;
+ value = pthread_getspecific(key_list[key]);
+ return !value ? FOSA_EINVAL : 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()
+{
+ int ret;
+
+ ret = sched_get_priority_max(SCHED_RR);
+
+ return ret ? errno : 0;
}
-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()
+{
+ int ret;
+
+ ret = sched_get_priority_min(SCHED_RR);
+
+ return ret ? errno : 0;
}
-int fosa_thread_attr_set_prio(frsh_thread_attr_t *attr, int prio)
+/**
+ * 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;
+ int ret;
+ struct sched_param param;
+
+ param.sched_priority = prio;
+ ret = pthread_attr_setschedpolicy(attr, SCHED_RR);
+ if (ret) return ret;
+
+ return pthread_attr_setschedparam(attr, ¶m);
}
-int fosa_thread_attr_get_prio (const frsh_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 ret;
+ struct sched_param param;
+
+ ret = pthread_attr_getschedparam(attr, ¶m);
+ if (ret) return ret;
- errno = EINVAL;
- return -1;
+ *prio = param.sched_priority;
+
+ return 0;
}
-int fosa_thread_set_prio(frsh_thread_id_t tid, int prio)
+/**
+ * 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;
- //}
+ int ret;
+ struct sched_param param;
+
+ param.sched_priority = prio;
- errno = EINVAL;
- return -1;
+ ret = sched_setscheduler(0, SCHED_RR, ¶m);
+
+ return ret ? errno : 0;
}
-int fosa_thread_get_prio (frsh_thread_id_t tid, int *prio)
+/**
+ * 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 ret;
+
+ ret = sched_getparam(0, ¶m);
+ *prio = param.sched_priority;
- errno = EINVAL;
- return -1;
+ return ret ? errno : 0;
}
/*******************************************************************
* synchronously wait. Signals carry an associated piece of
* information (an integer or a pointer) and are queued until they are
* accepted. Signals are identified by an integer signal number (of
- * the type frsh_signal_t) in the range FOSA_SIGNAL_MIN,
+ * the type fosa_signal_t) in the range FOSA_SIGNAL_MIN,
* FOSA_SIGNAL_MAX. This range is required to have at least <tbd>
* 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;
-
-int fosa_set_accepted_signals(frsh_signal_t set[], int size)
+/**
+ * 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
+ *
+ * Alternatively, in case of error the implementation is allowed to
+ * notify it to the system console and then terminate the FRSH
+ * implementation and dependant applications
+ **/
+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, ret;
+ fosa_thread_id_t self;
+ sigset_t sigset;
+ struct sigaction action;
+
+ ret = sigemptyset(&sigset);
+ if (ret) goto err;
+
+ action.sa_handler = SIG_DFL;
+ action.sa_mask = sigset;
+ action.sa_flags = SA_SIGINFO;
+ action.sa_sigaction = NULL;
+
+ for (i = 0; i < size; i++) {
+ ret = sigaddset(&sigset, set[i]);
+ if (ret) goto err;
+ ret = sigaction(set[i], &action, NULL);
+ if (ret) goto err;
+ }
+
+ self = fosa_thread_self();
+ if (__fosa_check_thread(&self)) {
+ ret = pthread_sigmask(SIG_BLOCK, &sigset, NULL);
+ if (ret) return ret;
+ } else {
+ ret = sigprocmask(SIG_BLOCK, &sigset, NULL);
+ if (ret) goto err;
+ }
+
+ return 0;
+err:
+ return errno;
}
-int fosa_signal_queue(frsh_signal_t signal,
- frsh_signal_info_t info,
- frsh_thread_id_t receiver)
+/**
+ * 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. In those implementations that do not support queueing a
+ * signal with information to a thread (such as POSIX), the signal may
+ * be sent to any thread that is waiting for this signal via
+ * fosa_signal_wait(). Portability can be ensured by having the receiver
+ * thread be the one who is waiting for the signal.
+ *
+ * In this implementation, this limitation has been overcome by means
+ * of the Linux specific capability of sending a timer event directly
+ * to a specific thread. Thus, we program a fake timer to fire immediately
+ * and notify such event to the requested receiver 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
+ *
+ * Alternatively, in case of error the implementation is allowed to
+ * notify it to the system console and then terminate the FRSH
+ * implementation and dependant applications
+ **/
+int fosa_signal_queue(fosa_signal_t signal,
+ fosa_signal_info_t info,
+ fosa_thread_id_t receiver)
{
- union sigval siginfo;
+ int ret;
+ timer_t fake_timer;
+ struct itimerspec fake_time;
+ struct sigevent fake_event;
+
+ ret = timer_create(FOSA_CLOCK_REALTIME, &fake_event, &fake_timer);
+ if (ret) goto err;
+
+ fake_time.it_value.tv_sec = fake_time.it_value.tv_nsec = 0;
+ fake_time.it_interval.tv_sec = fake_time.it_interval.tv_nsec = 0;
+ fake_event.sigev_notify = SIGEV_THREAD_ID | SIGEV_SIGNAL;
+ fake_event.sigev_signo = SIGRTMIN;
+ fake_event.sigev_value.sival_int = info.sival_int;
+ fake_event._sigev_un._tid = receiver.linux_tid;
+
+ ret = timer_settime(fake_timer, TIMER_ABSTIME, &fake_time, NULL);
+ if (ret) {
+ timer_delete(fake_timer);
+ goto err;
+ }
+
+ ret = timer_delete(fake_timer);
+ if (ret) goto err;
- siginfo.sival_int = info.sival_int;
- return sigqueue(receiver.linux_pid, signal, siginfo);
+ return 0;
+err:
+ return errno;
}
-int fosa_signal_wait (frsh_signal_t set[],
- int size,
- frsh_signal_t *signal_received,
- frsh_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
+ *
+ * Alternatively, in case of error the implementation is allowed to
+ * notify it to the system console and then terminate the FRSH
+ * implementation and dependant applications
+ **/
+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, ret;
+ sigset_t sigset;
+ siginfo_t siginfo;
+
+ ret = sigemptyset(&sigset);
+ if (ret) goto err;
+
+ for (i = 0; i < size; i++) {
+ ret = sigaddset(&sigset,set[i]);
+ if (ret) goto err;
+ }
+
+ ret = sigwaitinfo(&sigset, &siginfo);
+ if (ret) goto err;
+
+ if (info != NULL && signal_received != NULL)
+ *signal_received = siginfo.si_signo;
+ if (info != NULL)
+ *info = (fosa_signal_info_t) siginfo.si_value.sival_int;
return 0;
+err:
+ return errno;
}
-int fosa_signal_timedwait(frsh_signal_t set[],
- int size,
- frsh_signal_t *signal_received,
- frsh_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
+ *
+ * Alternatively, in case of error the implementation is allowed to
+ * notify it to the system console and then terminate the FRSH
+ * implementation and dependant applications
+ **/
+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, ret;
+ sigset_t signalset;
+ siginfo_t siginfo;
+
+ ret = sigemptyset(&signalset);
+ if (ret) goto err;
+
+ for (i = 0; i < size; i++) {
+ ret = sigaddset(&signalset,set[i]);
+ if (ret) goto err;
+ }
+
+ ret = sigtimedwait(&signalset,&siginfo,timeout);
+ if (ret) goto err;
+
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;
+err:
+ return errno;
}